Shop OBEX P1 Docs P2 Docs Learn Events
Logging either on the fly or post-deployment of the A.Bot — Parallax Forums

Logging either on the fly or post-deployment of the A.Bot

I'm wanting to try and log the maneuvers that I put my Activity Bot through.
Having finished the corresponding tutorial I guess I need to use the drive_getTicks function but I am unsure how to implement this in a way that will retrieve data created while the bot is "un-tethered" so to speak from the USB.
This may not be possible or this maybe an oversight of the obvious by me, please forgive either way....
thank you!
JP

Comments

  • There is a tutorial on using the SD card. I have used the SD card to record Ping readings. Later, I read the file on the SD card with my PC to copy the data to an Excel spreadsheet. The C program that does this is located at the link below.

    forums.parallax.com/discussion/comment/1332769/#Comment_1332769

    One problem is that when I wrote this, the libraries included the function "itoa()". That function converted an integer into text, but was removed from the newer directories.

    By saving the text representation to the SD card and separating values by "," or CR, the numbers can easily be imported into other programs.

    The sprint() or sprinti() function would have to be substituted for itoa() where ever it is called. The parameters for the itoa and sprint functions are different.

    atoi parameters are integer to convert, character string to hold converted digits, number base of the integer.

    int n = sprinti(buffer, "%d", x); // convert number to string, n is returned and is the length of the string, buffer is a character array long enough to hold the integer digits, x is the integer, %d is the formatting which converts the decimal (base 10) representation of x. sprinti only works with integers and saves significant code space.

    hope this helps
    Tom

  • Thanks Tom!

    Here also is an EEPROM example that stores navigation values between each maneuver.
    
    #include "simpletools.h"
    #include "abdrive.h"
    
    int left, right, address;
    
    int main()                    
    {
      address = 32768 - 4;
      
      print("DATA DURING TRAVEL\n\n");
    
      drive_goto(256, 256);
      pause(200);
      drive_getTicks(&left, &right);
        print("left = %d, right = %d\n", left, right);
      ee_putInt(left, address += 4);
      ee_putInt(right, address += 4);
    
      drive_goto(26, -25);
      pause(200);
      drive_getTicks(&left, &right);
        print("left = %d, right = %d\n", left, right);
      ee_putInt(left, address += 4);
      ee_putInt(right, address += 4);
    
      drive_goto(100, 100);
      pause(200);
      drive_getTicks(&left, &right);
        print("left = %d, right = %d\n", left, right);
      ee_putInt(left, address += 4);
      ee_putInt(right, address += 4);
      
      print("\nDATA THAT WAS LOGGED:\n\n");
    
      int endAddress = address;
      for(address = 32768; address < endAddress; address += 8)
      {
        left = ee_getInt(address); 
        right = ee_getInt(address + 4);
        print("left = %d, right = %d\n", left, right);
      }    
    }
    
  • DavidZemonDavidZemon Posts: 2,973
    edited 2016-01-22 20:52
    I'm going to push a totally different approach. PropWare is a C++ library that provides a great way to log to all kinds of different places.

    Let's say that right now, your code drives the Activity Bot to a certain place, then logs the number of ticks to the terminal. Simple. That program might look like this if you're using the Simple libraries (as Andy showed above)
    #include "simpletools.h"
    #include "abdrive.h"
    
    int main()                    
    {
      int left;
      int right;
    
      drive_goto(256, 256);
      pause(200);
      drive_getTicks(&left, &right);
      print("left = %d, right = %d\n", left, right);
    }
    

    If you want to use PropWare, you don't have to change much
    #include <PropWare/printer/printer.h>
    #include "abdrive.h"
    
    int main()                    
    {
      int left;
      int right;
    
      drive_goto(256, 256);
      pause(200);
      drive_getTicks(&left, &right);
      pwOut.printf("left = %d, right = %d\n", left, right);
    }
    

    From here, I'm going to add a line at the top that seems rather useless.... but you'll understand in a bit.
    #include <PropWare/printer/printer.h>
    #include "abdrive.h"
    
    using namespace PropWare;
    
    int main()                    
    {
      Printer logger = pwOut;
    
      int left;
      int right;
    
      drive_goto(256, 256);
      pause(200);
      drive_getTicks(&left, &right);
      logger.printf("left = %d, right = %d\n", left, right);
    }
    

    And now you can modify this to save to an SD card by adding a few lines to the top (to initialize your SD card) and then change a single word at the bottom:
    #include <PropWare/printer/printer.h>
    #include <PropWare/filesystem/fat/fatfilewriter.h>
    #include <PropWare/filesystem/sd.h>
    #include "abdrive.h"
    
    using namespace PropWare;
    
    int main()                    
    {
      const SD  driver;
      FatFS     filesystem(&driver);
      filesystem.mount();
      FatFileWriter writer(filesystem, "motorLog.csv");
      Printer filePrinter(&writer);
    
      Printer logger = filePrinter;
      
      int left;
      int right;
    
      drive_goto(256, 256);
      pause(200);
      drive_getTicks(&left, &right);
      logger.printf("left = %d, right = %d\n", left, right);
    }
    

    Now, you might think "wow! that's a lot of code at the top now!" And in this small example, it is a lot of lines. However, realize that after the line "Printer logger = filePrinter", there were no code changes. The entire rest of your program does not need to change. How cool is that?! :D Now you can quickly and easily switch between logging to the terminal and an SD card!
  • twm47099, and Andy L.

    Thank you both so very much!
    I cant wait to get home from work and try out the solutions you presented me with!

    JP
  • Ah choices are always good!
    I haven't used Prop ware (or much C++) yet but I'm not afraid :)
    Thank you for this , I find myself in a lot of head scratching situations at my desk, the more tools I have to free myself the better!
    Ill let you know how it goes David.

    JP
  • I feel like I'm receiving so much without giving!
    All 3 approaches (eventually) worked fine.The only reason for the delay was my inexperience with some of the terminology involved in swapping the functions out and being sure to declare and initialize everything properly.properly. I've a lot to learn clearly Tom! :)

    Andy I loaded the code straight away into EEPROM and ran it.The bot did the maneuvers, but where I became lost was I realized that this was something I would view through the terminal so therefore I needed to be attached to the USB right? (I built a stand for my bot that allows me to run code that spins the wheels while still on the desk) this is how I ran it the second time.Did I misunderstand? Is there a way to play out the maneuvers un-tethered and store the data in the on-board memory then come back and have it displayed in the terminal? I'm sorry for my nievete and thank you for your patience! Regardless its still a clean and entirely readable way to log the moves perhaps before actually performing them :)

    David looking at Propware everything seems to make sense (within the limited understanding I have as a whole about this stuff).I did the Propware for Windows.Its in C:\Propware.{BTW I'm Win 8.1 pro 32g RAM i7 4790K}
    I installed and configured everything correctly I believe.Perhaps I copied the code wrong as I kept getting this when I tried to load it:
    propWare.cpp:9:9: error: 'SD' does not name a type
    propWare.cpp:10:25: error: 'driver' was not declared in this scope
    propWare.cpp:13:24: error: 'printer' was not declared in this scope
    I just copied the code straight from the reply you sent yesterday.
    Please advise if you think I'm not setup correctly as I very much would like to add Propware to my arsenal!

    Thanks fellas,
    and now off to work :/ (boo!)
    JonPeyton


  • JonPeyton wrote: »
    David looking at Propware everything seems to make sense (within the limited understanding I have as a whole about this stuff).I did the Propware for Windows.Its in C:\Propware.{BTW I'm Win 8.1 pro 32g RAM i7 4790K}
    I installed and configured everything correctly I believe.Perhaps I copied the code wrong as I kept getting this when I tried to load it:
    propWare.cpp:9:9: error: 'SD' does not name a type
    propWare.cpp:10:25: error: 'driver' was not declared in this scope
    propWare.cpp:13:24: error: 'printer' was not declared in this scope
    I just copied the code straight from the reply you sent yesterday.
    Please advise if you think I'm not setup correctly as I very much would like to add Propware to my arsenal!

    Okay, your comments make me realize that I have not provided any kind of guidance for users which would help them decide between the "Windows" and "SimpleIDE" instructions that I provide. I've created an issue for this and will update the docs over the weekend.

    In the meantime, I'll simply tell you that you're going to want to use the "SimpleIDE" instructions. You can skip step 1 of those instructions since you already have that available under C:\PropWare.
    The other instructions are all intended for someone that wants to use PropWare's build system which is an alternative to SimpleIDE. I only recommend PropWare's build system if you are already familiar with the command line or you would prefer to use another IDE such as CLion or Eclipse.
  • dgatelydgately Posts: 1,630
    edited 2016-01-22 19:11
    I too have the same problem as JonPeyton... But, on Mac S X.

    Although I've been able to build PropWare projects from the command line, building from SimpleIDE has not been as successful. I've followed the SimpleIDE instructions for PropWare, downloading the "libraries & header files" (I copied those into /Learn/Simple Libraries/), and get the same results as Jon. So, looks like there's either a missing step or some configuration problem (BTW: I reset my environment to export $PropWarePath to point towards the newly downloaded PropWare directory, which I place in /Learn/Simple Libraries/). Not sure if that would affect SimpleIDE builds but did it as an extra measure :-)
    Project Directory: ~/PropCCode/testPWare/testPWareCPP/
    
    SimpleIDE Version 1.0.2
    ~/Documents/SimpleIDE/Learn/Simple Libraries/
    ~/Documents/SimpleIDE/ Updated on: 2015-11-19
    
    propeller-elf-gcc -v GCC 4.6.1 (propellergcc_v1_0_0_2435)
    propeller-elf-gcc -I . -L . -I ./../../../Documents/SimpleIDE/Learn/Simple Libraries/PropWare/include -L ./../../../Documents/SimpleIDE/Learn/Simple Libraries/PropWare/lib/lmm/ -I ./../../../Documents/SimpleIDE/Learn/Simple Libraries/PropWare/lib -I ~/Documents/SimpleIDE/Learn/Simple Libraries/Robotics/ActivityBot/libabdrive -L ~/Documents/SimpleIDE/Learn/Simple Libraries/Robotics/ActivityBot/libabdrive/lmm/ -I ~/Documents/SimpleIDE/Learn/Simple Libraries/Utility/libsimpletools -L ~/Documents/SimpleIDE/Learn/Simple Libraries/Utility/libsimpletools/lmm/ -I ~/Documents/SimpleIDE/Learn/Simple Libraries/PropWare/include/libpropeller -L ~/Documents/SimpleIDE/Learn/Simple Libraries/PropWare/include/libpropeller/lmm/ -I ~/Documents/SimpleIDE/Learn/Simple Libraries/TextDevices/libsimpletext -L ~/Documents/SimpleIDE/Learn/Simple Libraries/TextDevices/libsimpletext/lmm/ -I ~/Documents/SimpleIDE/Learn/Simple Libraries/Protocol/libsimplei2c -L ~/Documents/SimpleIDE/Learn/Simple Libraries/Protocol/libsimplei2c/lmm/ -I ~/Documents/SimpleIDE/Learn/Simple Libraries/TextDevices/libfdserial -L ~/Documents/SimpleIDE/Learn/Simple Libraries/TextDevices/libfdserial/lmm/ -o lmm/testPWareCPP.elf -Os -mlmm -Wall -m32bit-doubles -fno-exceptions -std=gnu++0x -fno-rtti -fno-threadsafe-statics -ffunction-sections -fdata-sections -Wl,--gc-sections testPWareCPP.cpp -lPropWare -lLibpropeller -lSimple -labdrive -lsimpletools -lpropeller -lsimpletext -lsimplei2c -lfdserial -lPropWare -lLibpropeller -lSimple -labdrive -lsimpletools -lpropeller -lsimpletext -lsimplei2c -lPropWare -lLibpropeller -lSimple -labdrive -lsimpletools -lpropeller -lsimpletext -lPropWare -lLibpropeller -lSimple -labdrive -lsimpletools -lpropeller -lPropWare -lLibpropeller -lSimple -labdrive -lsimpletools -lPropWare -lLibpropeller -lSimple -labdrive -lPropWare -lLibpropeller -lSimple -lPropWare -lLibpropeller -lPropWare
    testPWareCPP.cpp: In function 'int main()':
    testPWareCPP.cpp:10:9: error: 'SD' does not name a type
    testPWareCPP.cpp:11:25: error: 'driver' was not declared in this scope
    testPWareCPP.cpp:14:24: error: 'printer' was not declared in this scope
    Done. Build Failed!
    

    dgately
  • Doh! That's what I get for posting code without testing for compilation errors first. Try this:
    #include <PropWare/printer/printer.h>
    #include <PropWare/filesystem/sd.h>
    #include <PropWare/filesystem/fat/fatfilewriter.h>
    #include "abdrive.h"
    
    using namespace PropWare;
    
    int main()                    
    {
      const SD  driver;
      FatFS     filesystem(&driver);
      filesystem.mount();
      FatFileWriter writer(filesystem, "motorLog.csv");
      Printer filePrinter(&writer);
    
      Printer logger = filePrinter;
      
      int left;
      int right;
    
      drive_goto(256, 256);
      pause(200);
      drive_getTicks(&left, &right);
      logger.printf("left = %d, right = %d\n", left, right);
    }
    

    This did overflow when compiled with LMM, so be sure you're using CMM for your memory model.
  • I've also fixed the original post. All that I changed was adding an extra header include (sd.h) and changing "Printer filePrinter(&printer);" to "Printer filePrinter(&writer);"
  • About the EEPROM & USB, the display was just to show what was happening. You could use code in one program to log your travels, and another to display it. For convenience, you can add some startup code that travels and logs, then displays when you plug the USB back in (and maybe press/release RST).

    Use Load EEPROM & Run with the example below. Then, turn off power, unplug, and take it somewhere to navigate. Turn on power, if the P26 light turns on, let it do its navigation. If P27 turns on, press/release RST within 2 seconds, then P26 should turn on in another second. With P26 on, let do its navigation.

    When the navigation has completed (and logged), turn off power and bring to computer and plug in. Click Program and select Open Terminal. If the Enable/Disable button displays Enable, click it. If it displays Disable, leave it. Then, turn bot power on. If the light is P27, it'll show the logged data. If the light is P26, you'll have 2 seconds to press/release RST to make P27 come on and display the data.
    #include "simpletools.h"
    #include "abdrive.h"
    
    #define EE_MODE 32768
    #define EE_LAST 32768 + 4
    #define EE_DATA 32768 + 8  
    
    void logManeuvers(void);
    void displayLog(void);
    int ee_storeTicks(int left, int right, int address);
    int ee_getTicks(int *left, int *right, int address);
    
    int left, right;
    
    int main()                    
    {
      int address = EE_MODE;
      int mode = ee_getInt(address);
      ee_putInt(mode + 1, address);
      if( (mode % 2) == 1) 
      {
        high(26);
        pause(2000);
        logManeuvers();
      }
      else
      {
        high(27);
        pause(2000);
        displayLog();
      }
    }
    
    void logManeuvers(void)
    {
      int address = EE_DATA;
      print("DATA DURING TRAVEL\n\n");
      drive_goto(256, 256);
      pause(200);
      drive_getTicks(&left, &right);
      print("left = %d, right = %d\n", left, right);
      address = ee_storeTicks(left, right, address);
    
      drive_goto(26, -25);
      pause(200);
      drive_getTicks(&left, &right);
      print("left = %d, right = %d\n", left, right);
      address = ee_storeTicks(left, right, address);
    
      drive_goto(100, 100);
      pause(200);
      drive_getTicks(&left, &right);
      print("left = %d, right = %d\n", left, right);
      address = ee_storeTicks(left, right, address);
    
      print("\nDone!  Press/release RST to view data.\n\n");
    }
    
    void displayLog(void)
    {
      print("\nDATA THAT WAS LOGGED:\n\n");
      int endAddress = ee_getInt(EE_LAST);
      int address = EE_DATA;
      while(address < endAddress)
      {
        address = ee_getTicks(&left, &right, address);
        print("left = %d, right = %d\n", left, right);
      }    
    }
    
    int ee_storeTicks(int left, int right, int address)
    {
      //print("ee_storeTicks(%d, %d, %d) = ", left, right, address);
      ee_putInt(left, address);
      ee_putInt(right, address += 4);
      address += 4;
      ee_putInt(address, EE_LAST);
      //print("%d\n", address);
      return address;
    }    
    
    int ee_getTicks(int *left, int *right, int address)
    {
      *left = ee_getInt(address);
      *right = ee_getInt(address += 4);
      address += 4;
      //print("ee_getTicks(%d, %d, %d) = ", *left, *right, address-8);
      //print("%d\n", address);
      ee_putInt(address, EE_LAST);
      return address;
    }    
    
  • Works for me!

    Thanks!

    dgately
  • DavidZemonDavidZemon Posts: 2,973
    edited 2016-01-23 15:10
    @dgately, glad it worked!

    @JonPeyton and Andy:
    I've written up an EEPROM class for PropWare that uses the same interfaces (ScanCapable and PrintCapable) as the serial (UART) and SD card (FileWriter) classes. This will allow you to easily switch between terminal, eeprom, and SD card :)

    eeprom.h
    #pragma once
    
    #include <PropWare/i2c.h>
    #include <PropWare/printcapable.h>
    #include <PropWare/scancapable.h>
    
    namespace PropWare {
    
    /**
     * @brief   EEPROM reader/writer
     */
    class Eeprom: public PrintCapable,
                  public ScanCapable {
        public:
            /** First byte above the standard 32kB EEPROM */
            static const uint16_t DEFAULT_INITIAL_MEMORY_ADDRESS = 32 * 1024;
            /** Standard EEPROM I2C address used for Propeller microcontrollers */
            static const uint8_t  DEFAULT_DEVICE_ADDRESS         = 0x50 << 1;
    
        public:
            /**
             * @brief       Construct an instance that, by default, will read from and write to the standard EEPROM
             *
             * @param[in]   driver                  I2C bus driver
             * @param[in]   initialMemoryAddress    Byte of EEPROM that should be read from or written to first when using
             *                                      methods that do not accept an address as a parameter
             * @param[in]   deviceAddress           EEPROM address on the I2C bus (for instance, the default device
             *                                      address would be passed in as `0x50 << 1`, _not_ `0x50`)
             * @param[in]   autoIncrement           Should the memory address pointer be automatically incremented upon
             *                                      reading and writing bytes from and to the EEPROM, similar to
             *                                      reading/writing files
             */
            Eeprom(const I2C &driver = pwI2c,
                   const uint16_t initialMemoryAddress = DEFAULT_INITIAL_MEMORY_ADDRESS,
                   const uint8_t deviceAddress = DEFAULT_DEVICE_ADDRESS,
                   const bool autoIncrement = true)
                : m_driver(&driver),
                  m_memoryAddress(initialMemoryAddress),
                  m_deviceAddress(deviceAddress),
                  m_autoIncrement(autoIncrement) { }
    
            /**
             * @brief       Check that the EEPROM is responding
             *
             * @returns     True if the EEPROM is responding, false otherwise
             */
            bool ping() const {
                return this->m_driver->ping(this->m_deviceAddress);
            }
    
            /**
             * @brief       Place a byte of data into a specific address
             *
             * @param[in]   address     Address in EEPROM to place data
             * @param[in]   byte        Data to be written to EEPROM
             *
             * @returns     True if the data was successfully written, false otherwise
             */
            bool put(const uint16_t address, const uint8_t byte) const {
                // Wait for any current operation to finish
                while (!this->ping());
    
                return this->m_driver->put(this->m_deviceAddress, address, byte);
            }
    
            /**
             * @brief       Place multiple bytes of data into sequential memory locations in EEPROM
             *
             * @param[in]   startAddress    Address to store the first byte of data
             * @param[in]   bytes[]         Array of data - no null-terminator necessary
             * @param[in]   length          Number of bytes in the array that should be sent
             *
             * @returns     True if the data was successfully written, false otherwise
             */
            bool put(const uint16_t startAddress, const uint8_t bytes[], const size_t length) const {
                // Wait for any current operation to finish
                while (!this->ping());
    
                return this->m_driver->put(this->m_deviceAddress, startAddress, bytes, length);
            }
    
            /**
             * @see PropWare::PrintCapable::put_char
             *
             * @post    Internal memory address pointer will be incremented
             */
            virtual void put_char(const char c) {
                this->put(this->m_memoryAddress, (uint8_t) c);
                if (this->m_autoIncrement)
                    ++this->m_memoryAddress;
            }
    
            /**
             * @see PropWare::PrintCapable::puts
             *
             * @post    Internal memory address pointer will be incremented by the length of the string
             */
            virtual void puts(const char *string) {
                const size_t stringLength = strlen(string);
                this->put(this->m_memoryAddress, (const uint8_t *) string, stringLength);
                if (this->m_autoIncrement)
                    this->m_memoryAddress += stringLength;
            }
    
            /**
             * @brief       Read a byte from EEPROM
             *
             * @param[in]   address     Address in EEPROM to be read
             *
             * @returns     Data in EEPROM
             */
            uint8_t get(const uint16_t address) const {
                // Wait for any current operation to finish
                while (!this->ping());
    
                return this->m_driver->get(this->m_deviceAddress, address);
            }
    
            /**
             * @see PropWare::PrintCapable::get_char
             *
             * @post    Internal memory address pointer will be incremented
             */
            virtual char get_char() {
                const uint8_t byte = this->get(this->m_memoryAddress);
                if (this->m_autoIncrement)
                    ++this->m_memoryAddress;
                return byte;
            }
    
            /**
             * @brief       Retrieve the current address of the internal pointer
             *
             * @returns     Address in EEPROM used for reading or writing the next byte
             */
            uint16_t get_memory_address() const {
                return this->m_memoryAddress;
            }
    
            /**
             * @brief       Set the current address of the internal pointer
             *
             * @param[in]   address     Address in EEPROM used for reading or writing the next byte
             */
            void set_memory_address(const uint16_t address) {
                this->m_memoryAddress = address;
            }
    
            /**
             * @brief       Determine if auto incrementing of the internal address pointer is enabled
             *
             * @returns     True if enabled, false otherwise
             */
            bool is_auto_increment() const {
                return m_autoIncrement;
            }
    
            /**
             * @brief       Set auto incrementing of the internal address pointer to enabled or disabled
             *
             * @param[in]   autoIncrement   True to enabled, false to disable
             */
            void set_auto_increment(const bool autoIncrement) {
                m_autoIncrement = autoIncrement;
            }
    
        private:
            const I2C     *m_driver;
            uint16_t      m_memoryAddress;
            const uint8_t m_deviceAddress;
            bool          m_autoIncrement;
    };
    
    }
    

    PropWareEeprom_Demo.cpp
    #include <PropWare/printer/printer.h>
    #include <PropWare/eeprom.h>
    #include <PropWare/scanner.h>
    
    const uint8_t  MAGIC_ARRAY_1[] = "DCBA0";
    const size_t   ARRAY_SIZE_1    = sizeof(MAGIC_ARRAY_1);
    const char     MAGIC_ARRAY_2[] = "Hello, world!";
    const size_t   ARRAY_SIZE_2    = sizeof(MAGIC_ARRAY_2);
    const uint16_t TEST_ADDRESS    = 32 * 1024; // Place the data immediately above the first 32k of data
    
    /**
     * @example     PropWareEeprom_Demo.cpp
     *
     * Read from and write to the EEPROM that comes with your Propeller
     *
     * @include PropWare_Eeprom/CMakeLists.txt
     */
    int main() {
        PropWare::Eeprom eeprom;
    
        ////////////////////////////////////////////////////////////////////////////////////////////////
        // Here we have some core access of the EEPROM, passing it the address with every call. This is great for non-ASCII
        // data, but it gets tedious.
    
        pwOut << "EEPROM ack = " << eeprom.ping() << '\n';
    
        bool success = eeprom.put(TEST_ADDRESS, MAGIC_ARRAY_1, ARRAY_SIZE_1);
        pwOut << "Put status: " << success << '\n';
    
        pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS) << '\n';
        pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS + 1) << '\n';
        pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS + 2) << '\n';
        pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS + 3) << '\n';
        pwOut << "Received character: " << (char) eeprom.get(TEST_ADDRESS + 4) << '\n';
    
        ////////////////////////////////////////////////////////////////////////////////////////////////
        // This is great for ASCII data, because we have access to the Printer and Scanner classes.
    
        pwOut << "Notice that PropWare::Eeprom also implements the PropWare::PrintCapable \n"
            "and PropWare::ScanCapable interfaces. So we could also use the Propware::Printer \n"
            "and PropWare::Scanner objects for reading and writing.\n";
    
    
        PropWare::Printer eepromPrinter(&eeprom);
        PropWare::Scanner eepromScanner(&eeprom);
    
        // Reset the EEPROM address
        eeprom.set_memory_address(TEST_ADDRESS);
        // Note that the newline is required, or else the scanner won't know when to stop reading
        eepromPrinter << MAGIC_ARRAY_2 << '\n';
    
        char buffer[ARRAY_SIZE_2];
        // Reset the EEPROM address so that we can read what we just wrote
        eeprom.set_memory_address(TEST_ADDRESS);
        // Read from the EEPROM
        eepromScanner.gets(buffer, ARRAY_SIZE_2);
        pwOut << "Received \"" << buffer << "\" from the EEPROM!\n";
    
        return 0;
    }
    

    -- Edit --
    Documentation finished; Source code updated. I'll post a link to the source on GitHub once merged with the develop branch
Sign In or Register to comment.