In the last few chapters, you calibrated the grayscale sensors, the gyro and the compass. The calibration was saved inside XRCU, so it was still there after you turned XRCU OFF.
In this chapter, we will learn to save our own numbers inside XRCU in the same way. For example, your robot can remember a speed, a threshold, or how many times it has been turned ON.
XRCU has 2 kinds of memory:
| Normal memory | Saved data | |
|---|---|---|
| Used by | Normal variables, like int counter; | The Saved_data library |
| When XRCU turns OFF | Forgets everything | Remembers everything |
| When you upload a new program | Forgets everything | Remembers everything |
| Speed | Very fast | Slow to save, fast to read |
| How many times you can change it | No limit | About 10,000 saves |
Memory that forgets when the power is OFF is called volatile memory. Memory that remembers when the power is OFF is called non-volatile memory. So saved data is non-volatile.
Let's see the forgetting first. Here is a normal counter:
Let it count to 10, then turn XRCU OFF and ON again, and run the program. The counter starts from 1 again. XRCU has forgotten the old number!
XRCU keeps 32 places for your saved data. Each place is called a position, numbered from 1 to 32. You can think of them as 32 small lockers with numbers on the doors.
Each position holds 1 whole number from 0 to 65535.
You can see and change all 32 positions in the XRCU menu, without writing any code.
To use saved data in a program, include the Saved_data library at the top:
Then read_saved_data(position) gives the number saved at that position. For example, read_saved_data(1) gives the number at position 1.
Use the menu (not a program) to save your class number (or any number from 1 to 1000) at position 1. Then upload the program above and run it. Open the serial monitor. Does position 1 show your number?
Now turn XRCU OFF, wait 5 seconds, and turn it ON again. Look at position 1 on the Datapage, then run the program again. Is your number still there? What number does position 2 show?
Record a video showing the Datapage while you save the number, and the serial monitor after you turn XRCU OFF and ON again. Submit this video to your assignment portal at checkpoint 14.1.
write_saved_data(position, number) saves a number at a position. For example, write_saved_data(2, 123); saves 123 at position 2. The old number at position 2 is replaced.
Let's make a counter that XRCU does not forget. It counts how many times the program has started:
The number is saved the moment write_saved_data(...) runs. You do not need to call anything else.
Saved data is kept in a special memory inside XRCU. Each time a number changes, XRCU has to clean this memory and write it again. This memory can only be cleaned about 10,000 times. After that, it may stop working. Your saved data and your calibrations all share this same memory.
10,000 sounds like a lot. But loop() runs thousands of times every second! If you save inside loop() every time, the memory could be worn out in a few seconds.
Some good news:
Saving is also slow. It may take up to about 1 second, and your program waits until saving is done. So do not save while your robot is running a match!
Upload the counter program above and run it. Write down the count. Turn XRCU OFF and ON again, then run the program again. Do this 3 times. Does the count go up by 1 each time? Look at position 2 on the Datapage. What does it show?
Then change the program, so that clicking SW3 sets the count back to 0 and saves it. (Hint: use button3.isClicked() from the Buttons chapter, inside loop().) Click SW3, then turn XRCU OFF and ON again, and run the program. What count do you see now? Why is it 1, and not 0?
Record a video showing the serial monitor while you turn XRCU OFF and ON, and while you click SW3. Submit this video to your assignment portal at checkpoint 14.2.
A very useful job for saved data is a setting: a number that you choose with the buttons, like the speed of your robot. Then you do not need to upload a new program each time you want to change it!
When we load a setting, we should first check that the saved number makes sense. For example, our speed must be from 0 to 100. If the position has never been saved, it may show 65535, which is way too big. In that case, we use a safe starting value instead:
Change the program above into a speed setting program:
Upload and run it, then do these tests:
Record a video showing your fingers, the LED and the serial monitor during all 5 tests. Submit this video to your assignment portal at checkpoint 14.3.
Each position can only hold a whole number from 0 to 65535. If you save a number outside this range, you will read back a different number. For example, if you save -1, you will read back 65535.
To save a decimal number like 1.25, multiply it by 100 first, and save the whole number 125. After reading, divide it by 100.0 to get 1.25 back:
| Code | What it does |
|---|---|
| #include <Saved_data.h> | Lets us use read_saved_data(...) and write_saved_data(...). |
| read_saved_data(3) | Gives the number saved at position 3 (from 0 to 65535). |
| write_saved_data(3, 80) | Saves 80 at position 3. XRCU remembers it after turning OFF. |
Remember: