JM9 XRCU Tutorials 0.0.1a
Learn how to program XRCU
Loading...
Searching...
No Matches
Saved Data

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.

Forgetting and Remembering

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:

int counter;
void setup() {
Serial.begin(9600);
// A normal variable. It starts from 0 every time the program starts.
counter = 0;
}
void loop() {
// Count up by 1 every second.
counter = counter + 1;
Serial.println(counter);
delay(1000);
}

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!

The 32 Positions

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.

Note
XRCU keeps your calibrations (analog inputs, gyro, compass, motors) in other places. So the 32 positions are all yours. Saving to them will never break your calibrations.

Looking at Saved Data in the Menu

You can see and change all 32 positions in the XRCU menu, without writing any code.

  1. Turn ON XRCU. You will see the Homepage of the menu.
  2. Click SW2 2 times. You will see the Datapage: 16 boxes, each with a position number (white) and its saved value (blue).
  3. Click SW3. Now one box has a white frame. Click SW1 or SW2 to move the frame to another position. (Positions 17 to 32 are on the next screen.)
  4. Click SW3 again to change the value of that position:
    • SW1 makes the number go up, and SW2 makes it go down.
    • SW3 changes the step: 1, 50 or 1000 at a time.
    • SW4 saves the number and goes back to the boxes.
  5. Click SW4 again to go back. On the Datapage, SW4 runs your program as usual.
Warning
On a brand-new XRCU, a position that has never been saved usually shows 65535. But your kit may have been used by other students before you, so some positions may already have other numbers in them. Agree with your tutor which positions your team will use.

Reading Saved Data

To use saved data in a program, include the Saved_data library at the top:

#include <Saved_data.h>

Then read_saved_data(position) gives the number saved at that position. For example, read_saved_data(1) gives the number at position 1.

#include <Saved_data.h>
void setup() {
Serial.begin(9600);
}
void loop() {
// Read the numbers saved at position 1 and position 2.
int number1 = read_saved_data(1);
int number2 = read_saved_data(2);
Serial.print("Position 1: ");
Serial.print(number1);
Serial.print(" Position 2: ");
Serial.println(number2);
delay(500);
}
Note
The positions start from 1, not 0. read_saved_data(0) or read_saved_data(33) always gives 0, because there is no position 0 or 33.

Checkpoint 14.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.

Saving Data

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:

#include <Saved_data.h>
int count;
void setup() {
Serial.begin(9600);
// Step 1: Read the old count from position 2.
count = read_saved_data(2);
// Step 2: The program has just started, so add 1.
count = count + 1;
// Step 3: Save the new count back to position 2.
// This happens only once each time the program starts.
write_saved_data(2, count);
}
void loop() {
Serial.print("This program has started ");
Serial.print(count);
Serial.println(" times.");
delay(1000);
}

The number is saved the moment write_saved_data(...) runs. You do not need to call anything else.

Don't Wear Out the Memory!

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 the same number again does not clean the memory, so it does not wear it out.
  • Saving once each time the program starts (like the counter above) is fine. You would need to turn XRCU ON 10,000 times to wear it out.
Warning
Only save when a button is clicked (or once in setup()), never every time loop() runs.

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!

Checkpoint 14.2

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.

Saving a Setting

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:

#include <Saved_data.h>
int speed;
void setup() {
Serial.begin(9600);
// Load the speed from position 3.
speed = read_saved_data(3);
// Does the saved number make sense?
// Our speed must be from 0 to 100.
if (speed > 100) {
// No! It was never saved, or it is rubbish.
// Use a safe starting value instead.
speed = 50;
}
}
void loop() {
Serial.print("Speed: ");
Serial.println(speed);
delay(500);
}
Remarks
Keep a list of which position stores what, for example "position 3 = speed". Write it as a comment at the top of your program. Then you will not save 2 different settings at the same position by accident.

Checkpoint 14.3

Change the program above into a speed setting program:

  1. Load the speed from position 3, and use 50 if the number is bigger than 100 (like above).
  2. Each click of SW2 makes the speed go up by 1. Each click of SW1 makes the speed go down by 1. The speed must never go above 100 or below 0.
  3. Turn on pulse clicks for SW1 and SW2, so you can hold them.
  4. Each click of SW3 saves the speed at position 3, and prints Saved!. Turn the LED ON while saving, and OFF when saving is done.
  5. Print the speed on the serial monitor.

Upload and run it, then do these tests:

  1. Change the speed to 80, and click SW3 to save it.
  2. Turn XRCU OFF and ON again, and run the program. What speed do you see?
  3. Change the speed to 20, but do not click SW3.
  4. Turn XRCU OFF and ON again, and run the program. What speed do you see now? Why?
  5. Look at position 3 on the Datapage. What does it show?

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.

Negative Numbers and Decimals

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:

// Save 1.25: multiply by 100 first, so we save 125.
write_saved_data(4, 1.25 * 100);
// Read 125, then divide by 100.0 to get 1.25 again.
float gain = read_saved_data(4) / 100.0;
Note
Arduino also has a library called EEPROM. On XRCU, it uses the same memory where XRCU keeps your calibrations, so one wrong number could erase your gyro or compass calibration. Always use the Saved_data library for your own numbers.

Summary

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:

  • There are 32 positions, numbered from 1 to 32. Each holds a whole number from 0 to 65535.
  • Normal variables are forgotten when XRCU turns OFF. Saved data is remembered.
  • You can see and change saved data on the Datapage of the XRCU menu.
  • Only save when a button is clicked (or once in setup()), never every time loop() runs.
  • Check that a loaded number makes sense, and use a safe starting value if it does not.
Previous
Compound Eye