====== EEPROM ====== Nayon sok esetben problémát okoz az Arduinok esetén, hogy az adatok alapból nem perzisztálhatók. A perzisztáció azt jelenti, hogy az adatok nem törlődnek újraindítás, komplexebb esetben redundáns átkapcsolás után sem. Az Arduino operatív memóriája teljes mértékben törlődik ilyenkor. A legegyszerűbb megoldás az, hogy az Arduino EEPROM memória-területére tároljuk az ilyen adatokat, vagy egy külső memóriát alkalmazunk adattárolásra, ami lehet akár egy [[hu:arduino:micro_sd_card|SD kártya is]], de egyszerűbb egy külső EEPROM-ot beépíteni. Nyilván a megoldások között segít eligazítani, hogy mennyire akarjuk terhelni az Arduino saját EEPROM-ját, illetve milyen mennyiségű adatot akarunk perzisztálni. ===== Arduino EEPROM ===== A különböző Arduino board-ok eltérő méretű EEPROM-mal rendelkeznek: * ATmega328P: 1024 bájt * ATmega168: 512 bájt * ATmega8: 512 bájt * ATmega1280: 4096 bájt * ATmega2560: 4096 bájt Az EEPROM eléréséhez érdemes az EEPROM könyvtár funkcióit felhasználni: https://www.arduino.cc/en/Reference/EEPROM A belső EEPROM írásánál ügyelni kell arra, hogy az maximum nagyjából 100.000 írásciklusra alkalmaz. Ez talán soknak tűnik, de ha minden ciklusban adatokat próbálunk oda menteni, gyorsan elérhetjük élettartamának a végét. Nyilván érdemes az írásokat nem túl gyakran bekövetkező eseményekhez, vagy idő-triggerhez kötni. ==== Példaprogram az Arduino EEPROM-hoz ==== /* * EEPROM Write * * Stores values read from analog input 0 into the EEPROM. * These values will stay in the EEPROM when the board is * turned off and may be retrieved later by another sketch. */ #include /** the current address in the EEPROM (i.e. which byte we're going to write to next) **/ int addr = 0; void setup() { /** Empty setup. **/ } void loop() { /*** Need to divide by 4 because analog inputs range from 0 to 1023 and each byte of the EEPROM can only hold a value from 0 to 255. ***/ int val = analogRead(0) / 4; /*** Write the value to the appropriate byte of the EEPROM. these values will remain there when the board is turned off. ***/ EEPROM.write(addr, val); /*** Advance to the next address, when at the end restart at the beginning. Larger AVR processors have larger EEPROM sizes, E.g: - Arduno Duemilanove: 512b EEPROM storage. - Arduino Uno: 1kb EEPROM storage. - Arduino Mega: 4kb EEPROM storage. Rather than hard-coding the length, you should use the pre-provided length function. This will make your code portable to all AVR processors. ***/ addr = addr + 1; if (addr == EEPROM.length()) { addr = 0; } /*** As the EEPROM sizes are powers of two, wrapping (preventing overflow) of an EEPROM address is also doable by a bitwise and of the length - 1. ++addr &= EEPROM.length() - 1; ***/ delay(100); } {{ :wiki:arduino:at24c256.png?150|AT24C256 I²C EEPROM modul}} ===== AT24C256 I²C EEPROM IC és modul ===== Ebben az esetben az EEPROM funkció [[hu:comm:bus_i2c|I²C]]-n keresztül érhető el. Mivel jó eséllyel úgyis alkalmazunk pár másik [[hu:arduino:comm_example#arduino_i2c_com|Arduino I²C kommunikációs egységet]] is, így már a memóriakezelés nem fog további értékes pin-eket foglalni. Ennek az IC-nek két változata van, az AT24C128 128 kBit - 16 kByte, míg a AT24C256 256 kBit - 32 kByte címezhető, törölhető, de perzisztens adatterületet tartalmaz. Az írás / olvasás bájtonként vagy laponként (64 bájt) történhet. ==== AT24C256 technikai adatok ==== * Tápfeszültség: * (alacsony feszültésgű mód): 1,8..3,6 V * (normál feszültésgű mód): 2,7..5,5 V * Kommunikáció: [[hu:comm:bus_i2c|I²C]] * Átlapolás mód: 64 byte * I²C frekvencia kompatibilitás: 1 MHz (5V), 400 kHz (2,7..2,5V), 100 kHz (1,8V) * Írásciklusok maximális száma: 1 millió * Működési hőmérséklet: -55..125 °C * A lábak feszültségtűrése a GND-hez képest: -1..7 V * Maximális tápfeszültség: 6,25 V * Kimeneti áram: 5,0 mA ==== AT24C256 IC lábkiosztás ==== {{:wiki:arduino:at24c256_ic.png|AT24C256 IC lábkiosztás}} **A0, A1:** I²C cím \\ **SDA:** I²C adatport \\ **SCL:** I²C órajel port \\ **WP:** írásvédelem az IC-re \\ **NC:** nincs bekötve \\ Az IC külön is beszerezhető, de egyszerűbb a modult beszerzi, akkor már nem kell bütykölni az [[hu:comm:bus_i2c|I²C]] felhúzóellenállásaival, címzés jumperekkel, és a "drótozással". ==== AT24C256 címkiosztás ==== Az EEPROM címe az A0, A1 pinek (vagy modul esetén jumperek) segítségével így alakul: {{:wiki:arduino:at24c256_adr.png|AT24C256 címkiosztás}} ==== AT24C256 telegram-felépítés ==== {{:wiki:arduino:at24c256_teleg.png|AT24C256 telegram-felépítés}} ==== Vezetékezés (modul) ==== {{:wiki:arduino:at24c256_wiring.png?600|AT24C256 I²C EEPROM modul vezetékezés}} ==== Szoftver ==== A modulhoz alkalmazásprogram a Githubról is letölthető: https://github.com/cyberp/AT24Cx /* * Use the I2C bus with EEPROM 24LC64 * Sketch: eeprom.ino * * Author: hkhijhe * Date: 01/10/2010 * * */ #include void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) { int rdata = data; Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress & 0xFF)); // LSB Wire.write(rdata); Wire.endTransmission(); } // WARNING: address is a page address, 6-bit end will wrap around // also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) { Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddresspage >> 8)); // MSB Wire.write((int)(eeaddresspage & 0xFF)); // LSB byte c; for ( c = 0; c < length; c++) Wire.write(data[c]); Wire.endTransmission(); } byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) { byte rdata = 0xFF; Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress & 0xFF)); // LSB Wire.endTransmission(); Wire.requestFrom(deviceaddress,1); if (Wire.available()) rdata = Wire.read(); return rdata; } // maybe let's not read more than 30 or 32 bytes at a time! void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) { Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress & 0xFF)); // LSB Wire.endTransmission(); Wire.requestFrom(deviceaddress,length); int c = 0; for ( c = 0; c < length; c++ ) if (Wire.available()) buffer[c] = Wire.read(); } void setup() { char somedata[] = "this is data from the eeprom"; // data to write Wire.begin(); // initialise the connection Serial.begin(9600); i2c_eeprom_write_page(0x50, 0, (byte *)somedata, sizeof(somedata)); // write to EEPROM delay(100); //add a small delay Serial.println("Memory written"); } void loop() { int addr=0; //first address byte b = i2c_eeprom_read_byte(0x50, 0); // access the first address from the memory while (b!=0) { Serial.print((char)b); //print content to serial port addr++; //increase address b = i2c_eeprom_read_byte(0x50, addr); //access an address from the memory } Serial.println(" "); delay(2000); }