Space Coast Florida
Offline
Jr. Member
Karma: 0
Posts: 58
|
 |
« on: January 16, 2013, 10:15:08 am » |
I have a project that uses a state machine with a master counter. The counter will have a maximum value of 750 or so. The state will be no larger than 50. As the counter updates every second it needs to be stored along with the state. The life span of the EEPROM rules him out so I decided to use the leftover space on the RTC memory map. On power up I will read the contents of the ram to get state and counter values (If there was a power outage the numbers will not be state = 0 and counter = 0) and plug those values into the program during setup so that the state machine can resume where it left off.
.....So the question is how best to cut up that 750 number to store it in a couple of bytes on the RTC and then to reassemble the number after reading from the RAM.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #1 on: January 16, 2013, 10:58:41 am » |
So the question is how best to cut up that 750 number highByte() and lowByte(). and then to reassemble the number after reading from the RAM. word().
|
|
|
|
|
Logged
|
|
|
|
|
Space Coast Florida
Offline
Jr. Member
Karma: 0
Posts: 58
|
 |
« Reply #2 on: January 16, 2013, 01:51:19 pm » |
Word! have you got any example code showing how to implement such a thing?
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #3 on: January 16, 2013, 02:38:20 pm » |
Did you bother looking at the reference page? http://arduino.cc/en/Reference/WordCast
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Online
Brattain Member
Karma: 240
Posts: 16457
Available for Design & Build services
|
 |
« Reply #4 on: January 16, 2013, 03:10:48 pm » |
Need the Wire page too. With DS1307, start by setting the register pointer to byte 56 where the battery backed SRAM starts. Then do 2 Wire.send messages to send the data over.
Same for reading it back. Set the register pointer, then do 2 Wire.read (wire.receive?) to bring the 2 bytes back.
|
|
|
|
|
Logged
|
|
|
|
|
Space Coast Florida
Offline
Jr. Member
Karma: 0
Posts: 58
|
 |
« Reply #5 on: January 16, 2013, 03:45:58 pm » |
I did and found it rather terse. I have established two way communications with the RTC that is working with only a few bugs. The code is ugly and I don't understand everything going on yet but the real issue is the smashing and reconstruction of the data.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Online
Brattain Member
Karma: 240
Posts: 16457
Available for Design & Build services
|
 |
« Reply #6 on: January 16, 2013, 04:12:38 pm » |
You have the number stored using data type int, yes? int bigNumber = 750;
To send it out, after the address is set up: Wire.write (highByte(bigNumber)); Wire.write (lowByte(bigNumber));
to put it back, after the address is set up: upperByte = Wire.read(); lowerByte = Wire.read();
then bigNumber = word(upperByte, lowerByte); or bigNumber = (upperByte <<8) + lowerByte; // shift upper bits into upper byte location, add in lower bits
or without interim storage: bigNumber = (Wire.read() << 8) + Wire.read();
http://arduino.cc/en/Reference/Wirehttp://arduino.cc/en/Reference/WireWritehttp://arduino.cc/en/Reference/WireRead
|
|
|
|
|
Logged
|
|
|
|
|
Space Coast Florida
Offline
Jr. Member
Karma: 0
Posts: 58
|
 |
« Reply #7 on: January 16, 2013, 04:30:26 pm » |
You have the number stored using data type int, yes? No I used Byte which was what the example showed. It seemed right should I change it? I will post the trimmed down example I am working with. /* Q(1-2) - (Q1) Memory initialization (Q2) RTC - Memory Dump */
#include "Wire.h" #define DS1307_I2C_ADDRESS 0x68 // This is the I2C address #define I2C_WRITE Wire.write #define I2C_READ Wire.read // Global Variables int command = 0; // This is the command char, in ascii form, sent from the serial port int i; long previousMillis = 0; // will store last time Temp was updated byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; byte test; byte zero; byte highbyte; byte lowbyte; byte state;
// Convert normal decimal numbers to binary coded decimal byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); }
// Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); }
void setup() { Wire.begin(); Serial.begin(57600); zero=0x00; }
void loop() { if (Serial.available()) { // Look for char in serial que and process if found command = Serial.read();
if (command == 81 || command == 113) { //If command = "Qq" RTC1307 Memory Functions delay(100); if (Serial.available()) { command = Serial.read(); if (command == 49) { //If command = "1" RTC1307 Initialize Memory - All Data will be set to // 255 (0xff). Therefore 255 or 0 will be an invalid value. Wire.beginTransmission(DS1307_I2C_ADDRESS); // 255 will be the init value and 0 will be considered // an error that occurs when the RTC is in Battery mode.
Wire.endTransmission(); Wire.beginTransmission(DS1307_I2C_ADDRESS);
// load dummy values to read back I2C_WRITE(0X08); // Set the register pointer to 33 for second half of registers. Only 32 writes per connection allowed. I2C_WRITE(24); I2C_WRITE(0X09); // Set the register pointer to 33 for second half of registers. Only 32 writes per connection allowed. I2C_WRITE(52); I2C_WRITE(0X0A); // Set the register pointer to 33 for second half of registers. Only 32 writes per connection allowed. I2C_WRITE(200);
Wire.endTransmission();
Serial.println(": RTC1307 Initialized Memory"); } else if (command == 50) { //If command = "2" RTC1307 Memory Dump
Serial.println(": RTC 1307 Dump Begin"); Wire.beginTransmission(DS1307_I2C_ADDRESS); I2C_WRITE(0x08); // Set the register pointer to (0x08) to read first memory byte Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 1); // In this case only read one byte state = Wire.read(); //Serial.println(": RTC 1307 Dump Begin"); Wire.beginTransmission(DS1307_I2C_ADDRESS); I2C_WRITE(0x09); // Set the register pointer to (0x08) to read first memory byte Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 3); // In this case only read one by highbyte = Wire.read();
Wire.beginTransmission(DS1307_I2C_ADDRESS); I2C_WRITE(0x20); Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 32); for (i = 32; i <= 63; i++) { //Register 32-63 - only 32 registers allowed per I2C connection test = I2C_READ(); Serial.print(i); Serial.print(": "); Serial.print(test, DEC); Serial.print(" : "); Serial.println(test, HEX); } Serial.println(" RTC1307 Dump end"); } } } Serial.print("Command: "); Serial.println(command); // Echo command CHAR in ascii that was sent } command = 0; // reset command delay(100); } //*****************************************************The End***********************
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Online
Brattain Member
Karma: 240
Posts: 16457
Available for Design & Build services
|
 |
« Reply #8 on: January 16, 2013, 04:52:54 pm » |
You can only store 0-255 in a byte. To store 0-65535 (which is where 750 fits in) you need to use an int.
|
|
|
|
|
Logged
|
|
|
|
|
Space Coast Florida
Offline
Jr. Member
Karma: 0
Posts: 58
|
 |
« Reply #9 on: January 16, 2013, 07:03:26 pm » |
You can only store 0-255 in a byte. To store 0-65535 (which is where 750 fits in) you need to use an int. Check! Makes sense. I was chopping it up in hundreds tens and ones. So 65535 is represented by two bytes. Int is doubleprecision ..Highbyte & Lowbyte.... Word puts them together.....got it Thank you for help!
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Boston area, metrowest
Online
Brattain Member
Karma: 240
Posts: 16457
Available for Design & Build services
|
 |
« Reply #10 on: January 16, 2013, 07:17:00 pm » |
"Int is doubleprecision" Well, it's 16 bits anyway 
|
|
|
|
|
Logged
|
|
|
|
|
Space Coast Florida
Offline
Jr. Member
Karma: 0
Posts: 58
|
 |
« Reply #11 on: January 20, 2013, 05:55:47 pm » |
OK, Some great help so far I have gotten this much running /* * Q(1-2) - (Q1) Memory Load (Q2) RTC - Memory Read */ #include "Wire.h" #define DS1307_I2C_ADDRESS 0x68 // This is the I2C address // Global Variables int command = 0; // This is the command char, in ascii form, sent from the serial port byte zero; int state = 50; // State machine variable int counter = 4; // Master counter variable int magnum1 = 99; // dummy var int magnum2 = 99; // dummy var
void setup() { Wire.begin(); // join i2c bus Serial.begin(57600); zero=0x00; // not sure what this is for }
void loop() { if (Serial.available()) { // Look for char in serial que and process if found command = Serial.read();
if (command == 81 || command == 113) { //If command = "Qq" RTC1307 Memory Functions delay(100); if (Serial.available()) { command = Serial.read(); if (command == 49) { //If command = "1" load data to RAM Wire.beginTransmission(DS1307_I2C_ADDRESS); // 255 will be the init value and 0 will be considered Wire.write(32); // Set the register pointer to before data location Wire.write(magnum1); // Write magic number before storing data Wire.write(state); // Store State variable Wire.write(counter >> 8); // writes the high byte of counter Wire.write(counter & 0xFF); // writes the low byte of counter Wire.write(magnum2); // Write magic number after storing data Wire.endTransmission();
Serial.println("Data Stored"); } else if (command == 50) { //If command = "2" Read data from RAM Serial.println("Begin Read"); Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.write(zero); // not sure what this is for Wire.endTransmission();
Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.write(0x20); // not sure what this is doing Wire.endTransmission(); Wire.requestFrom(DS1307_I2C_ADDRESS, 32); // Set pointer to the first byte of data
magnum1 = (Wire.read()); //magic number written before data write state = (Wire.read()); // Read state data counter = (Wire.read() << 8) + Wire.read(); // Read first byte shift left read second byte magnum2 = (Wire.read()); // Read Magic number written after data write Serial.print(" Magic Number = "); Serial.println(magnum1); Serial.print(" State = "); Serial.println(state); Serial.print(" Counter = "); Serial.println(counter); Serial.print(" Magic Number = "); Serial.println(magnum2); Serial.println(" RTC1307 Dump end"); } } } } command = 0; // reset command delay(100); } //********************************
now to figure out how to generate a random magic number
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #12 on: January 20, 2013, 06:35:55 pm » |
Is it OK if the random number has no magic properties?
|
|
|
|
|
Logged
|
|
|
|
|
Space Coast Florida
Offline
Jr. Member
Karma: 0
Posts: 58
|
 |
« Reply #13 on: January 20, 2013, 06:57:04 pm » |
Indeed
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #14 on: January 21, 2013, 07:12:32 am » |
The random() function will return a pseudo-random number. For most purposes, that is good enough. The whole topic of true random numbers has been beaten to death here, so I won't go into all that you have to do to get true random numbers. Or, how to properly seed the random number generator.
|
|
|
|
|
Logged
|
|
|
|
|
|