Disconnect everything but the USB.
Cancel SerialMonitor window/s.
Since you're messing with two different boards (which can make for some aggro) make certain that you have the right Board selected (in 'Tools').
Disconnect everything but the USB.
Cancel SerialMonitor window/s.
Since you're messing with two different boards (which can make for some aggro) make certain that you have the right Board selected (in 'Tools').
@adamaero As for your original question, what you wrote in post #4 will do it, provided the receiving code is smart enough to sense the delay at the end. Your 10 bytes (5 ints, presuming a 16-bit int), will take about 4 ms to send, followed by 996 mS of silence, so it could actually work. Primitive, but fits stated requirements. If you change your processor, and suddenly your code automatically sends 4-byte ints, you'd better tell the 'other team'.
I needed to put this into setup of receiving program:
while (!Serial);
Still working on the rest...
// Leo. receive
#include <EEPROM.h>
const int EEPROM_SIZE = 512; // Define the size of EEPROM available on the Leonardo
int addr = 0; // EEPROM address pointer
// Time offset for CST (Central Standard Time) in seconds
const long cstOffset = -6 * 3600; // CST is UTC-6
boolean one = true;
void setup() {
Serial.begin(9600);
while (!Serial);
Serial1.begin(38400);
Serial.println("EEPROM Data:");
for (int i = 0; i < EEPROM_SIZE; i += sizeof(unsigned long) + sizeof(int)) {
unsigned long timestamp;
int value;
EEPROM.get(i, timestamp);
EEPROM.get(i + sizeof(unsigned long), value);
// Adjust timestamp to CST
timestamp += cstOffset;
Serial.print("UTC: ");
Serial.println(timestamp);
// Convert time
printCSTTime(timestamp);
Serial.print(i);
Serial.print(", Value: ");
Serial.println(value);
}
}
void loop() {
static char buffer[sizeof(int)];
static int bufferIndex = 0;
static bool receiving = false;
if (one == true)
{
Serial.print("loop print once");
one = false;
}
while (Serial1.available()) {
char receivedChar = Serial1.read();
if (receivedChar == ',') {
if (receiving) {
// End of an integer, convert and store it
int receivedValue = atoi(buffer);
unsigned long currentTime = millis();
EEPROM.put(addr, currentTime);
addr += sizeof(unsigned long);
EEPROM.put(addr, receivedValue);
addr += sizeof(int);
if (addr >= EEPROM_SIZE) {
addr = 0; // Start writing from the beginning when EEPROM is full
}
Serial.println("Received: " + String(receivedValue));
bufferIndex = 0;
receiving = false;
}
} else {
// Add the received character to the buffer
buffer[bufferIndex++] = receivedChar;
// Check for buffer overflow
if (bufferIndex >= sizeof(buffer) - 1) {
bufferIndex = 0;
receiving = false;
} else {
receiving = true;
}
}
}
}
void printCSTTime(unsigned long timestamp) {
// Calculate CST time components (hour, minute, second)
int hours = (timestamp % 86400) / 3600;
int minutes = (timestamp % 3600) / 60;
int seconds = timestamp % 60;
String ampm = (hours < 12) ? " AM" : " PM";
// Adjust hours to be in 12-hour format
if (hours > 12)
hours -= 12;
Serial.print("CST: ");
Serial.print(hours);
Serial.print(":");
if (minutes < 10) Serial.print("0");
Serial.print(minutes);
Serial.print(":");
if (seconds < 10) Serial.print("0");
Serial.print(seconds);
Serial.println(ampm);
}
Serial monitor
EEPROM Data:
UTC: 19462
CST: 5:24:22 AM
0, Value: 0
UTC: 19496
CST: 5:24:56 AM
6, Value: 0
UTC: 19528
CST: 5:25:28 AM
12, Value: 0
UTC: 19562
CST: 5:26:02 AM
18, Value: 0
UTC: 19595
CST: 5:26:35 AM
24, Value: 0
UTC: 19629
CST: 5:27:09 AM
30, Value: 0
UTC: 19662
CST: 5:27:42 AM
36, Value: 0
I have to re-upload to see this. Pressing reset on the Leonardo doesn't do anything. The new sent data is also not displayed. All values are zero.
Start by having the TX unit send 123 and confirm that the RX unit gets 123.
As is often the case, the more we dig, the more we uncover. I've got better things to do than continue to pry for details. Good luck with your project.
What details? I've given all. Objective: have Uno send some random integers to a Leonardo; same them to EEPROM with the time they were received. That's it.
Everyone seems to be trying to change that to a million other things. I will try to create a different more basic program to send 123 and confirm 123 was sent...
I didn't think the original goal was super complicated. I thought I was just doing something minor wrong.
// Arduino Uno Send
void setup() {
Serial.begin(38400);
}
void loop() {
int integersToSend[] = {123};
for (int i = 0; i < 1; i++) {
Serial.write((byte*)&integersToSend[i], sizeof(int));
delay(1000);
Serial.write(',');
}
}
// Leo. receive
int receivedInt;
void setup() {
Serial.begin(38400);
while (!Serial);
Serial.setTimeout(100); // adjust as needed
Serial.println("Waiting for data...");
}
void loop() {
if (Serial.available() > 0) {
receivedInt = Serial.parseInt();
if (Serial.read() == ',') {
Serial.print("Received integer: ");
Serial.println(receivedInt);
} else {
Serial.println("Error: Invalid data format");
}
}
}
Waiting for data...
That's it. I press reset on the Uno and cycle the power. Nothing.
You are doing some thing major wrong.
@camsysca pointed out in Reply #2
Your send routine is sending a number as ASCII characters, but your receive routine thinks you should be receiving ints. One or the other needs to change.
You are now doing the reverse of this. Sending the bytes of the integer, but trying to read them as characters.
My recommendation has been to send and receive the integers as characters. It will be more simple and reliable. You have the models to follow in Serial Input Basics.
thanks. I'll convert them
// Uno send
void setup() {
Serial.begin(38400);
}
void loop() {
int integersToSend[] = {123};
for (int i = 0; i < 1; i++) {
char buffer[10];
itoa(integersToSend[i], buffer, 10);
Serial.print(buffer);
delay(1000);
Serial.write(',');
}
}
// Leo receive
String receivedData = "";
boolean newData = false;
void setup()
{
Serial.begin(9600);
while (!Serial);
Serial1.begin(38400);
Serial1.setTimeout(100); // adjust as needed
Serial1.println("Waiting for data...");
}
void loop()
{
if (Serial1.available() > 0)
{
char incomingChar = Serial1.read();
if (incomingChar == ',')
{
Serial.print("Received data: ");
Serial.println(receivedData);
receivedData = ""; // Reset the received data string
newData = false;
}
else
{
receivedData += incomingChar; // Append the character to the received data string
newData = true;
}
}
}
That works.
Great. Chars on both ends.
You do not need itoa on the sending end. Serial.print() will work fine to send the ascii characters of the integer.
Strings are a not a good idea with small memory processors. You should not use them on the receive end.
Follow the model of Serial Input Basic to send the comma separated variables in a start/end marker frame. Then follow the receive example, and then parse with strtok and convert back to integers with atoi.
// Leo. receive
#include <EEPROM.h>
const int EEPROM_SIZE = 512; // Define the size of EEPROM available on the Leonardo
int addr = 0; // EEPROM address pointer
// Time offset for CST (Central Standard Time) in seconds
const long cstOffset = -6 * 3600; // CST is UTC-6
boolean one = true;
void setup() {
Serial.begin(9600);
while (!Serial);
Serial1.begin(38400);
Serial.println("EEPROM Data:");
for (int i = 0; i < EEPROM_SIZE; i += sizeof(unsigned long) + sizeof(int)) {
unsigned long timestamp;
int value;
EEPROM.get(i, timestamp);
EEPROM.get(i + sizeof(unsigned long), value);
// Adjust timestamp to CST
timestamp += cstOffset;
Serial.print("UTC: ");
Serial.println(timestamp);
// Convert time
printCSTTime(timestamp);
Serial.print(i);
Serial.print(", Value: ");
Serial.println(value);
}
}
void loop() {
static char buffer[20];
static int bufferIndex = 0;
static bool receiving = false;
if (one == true)
{
Serial.print("loop print once");
one = false;
}
while (Serial1.available()) {
char receivedChar = Serial1.read();
if (receivedChar == ',') {
if (receiving) {
// End of data, process the received string
buffer[bufferIndex] = '\0'; // Null-terminate the string
unsigned long currentTime = millis();
EEPROM.put(addr, currentTime);
addr += sizeof(unsigned long);
EEPROM.put(addr, atoi(buffer));
addr += sizeof(int);
if (addr >= EEPROM_SIZE) {
addr = 0; // Start writing from the beginning when EEPROM is full
}
Serial.println("Received: " + String(buffer));
bufferIndex = 0;
receiving = false;
}
} else {
// Add the received character to the buffer
buffer[bufferIndex++] = receivedChar;
// Check for buffer overflow
if (bufferIndex >= sizeof(buffer) - 1) {
bufferIndex = 0;
receiving = false;
} else {
receiving = true;
}
}
}
}
void printCSTTime(unsigned long timestamp) {
// Calculate CST time components (hour, minute, second)
int hours = (timestamp % 86400) / 3600;
int minutes = (timestamp % 3600) / 60;
int seconds = timestamp % 60;
String ampm = (hours < 12) ? " AM" : " PM";
// Adjust hours to be in 12-hour format
if (hours > 12)
hours -= 12;
Serial.print("CST: ");
Serial.print(hours);
Serial.print(":");
if (minutes < 10) Serial.print("0");
Serial.print(minutes);
Serial.print(":");
if (seconds < 10) Serial.print("0");
Serial.print(seconds);
Serial.println(ampm);
}
Mostly works.
I have to re-upload every time I want to see the EEPROM data though
Time is off too
(I am going to hold off on making the sent data more specific with frame markers because I really do not know what this application is for. It's something to do with RS232. I would rather have the sent data more open ended in order to retrofit to whatever this is for.)
If for development purposes you want to read and display the eeprom values in loop() you can add a button or serial input to trigger to read.
Time is off too
unsigned long currentTime = millis();
EEPROM.put(addr, currentTime);
You are saving a millis() value into the eeprom, but then want to convert it into a "real world" clock time.
EEPROM.get(i, timestamp);
Serial.print("UTC: ");
Serial.println(timestamp);
// Convert time
printCSTTime(timestamp);
If you want to store the time an integer is received you will need to have some time source or reference time in the program. You just can't convert from millis() to UTC the way you do.
Ok, now I'm told the data is natural numbers 0-60 and is sent like this:
if (mySerial.available())
There is no delimiter of any kind. Or maybe it is newline?
I highly doubt it's sent this way.
#include <EEPROM.h>
const int timeRefreshDisplay = 30000;
const int EEPROM_SIZE = 512; // Define the size of EEPROM available
int addr = 0; // EEPROM address pointer
unsigned long programStartTime;
unsigned long lastDisplayTime = 0;
boolean displayInProgress = false;
void setup() {
Serial.begin(115200);
while (!Serial);
Serial1.begin(9600);
displayEEPROMData();
programStartTime = millis(); // Record program start time
}
void printTime(unsigned long timestamp) {
// Calculate time components (hour, minute, second)
int hours = (timestamp / 1000) % 86400 / 3600;
int minutes = (timestamp / 1000) % 3600 / 60;
int seconds = (timestamp / 1000) % 60;
if (hours < 10) Serial.print("0");
Serial.print(hours);
Serial.print(":");
if (minutes < 10) Serial.print("0");
Serial.print(minutes);
Serial.print(":");
if (seconds < 10) Serial.print("0");
Serial.print(seconds);
}
void displayEEPROMData() {
// Display all positions stored in EEPROM
Serial.println("EEPROM:");
for (int i = 0; i < EEPROM_SIZE; i += sizeof(unsigned long) + sizeof(int)) {
if (i >= EEPROM_SIZE) {
i = 0; // Start reading from the beginning when reaching the end of EEPROM
}
unsigned long timestamp;
int value;
EEPROM.get(i, timestamp);
EEPROM.get(i + sizeof(unsigned long), value);
// Calculate the timestamp relative to the program start time
unsigned long currentTimestamp = programStartTime + timestamp;
// Display position data with timestamp in HH:MM:SS format
Serial.print(String(i / (sizeof(unsigned long) + sizeof(int)) + 1) + ": ");
printTime(currentTimestamp);
Serial.println(", " + String(value));
}
}
void loop() {
if (Serial1.available()) {
char receivedData[50];
int dataLength = Serial1.readBytesUntil('\n', receivedData, sizeof(receivedData) - 1);
receivedData[dataLength] = '\0'; // Null-terminate the string
int receivedValue = atoi(receivedData); // Convert the entire string to an integer
// Calculate the timestamp based on program start time
unsigned long currentTimestamp = programStartTime + millis();
// Store the received timestamp and value in EEPROM
EEPROM.put(addr, currentTimestamp);
addr += sizeof(currentTimestamp);
if (addr >= EEPROM_SIZE) {
addr = 0; // Start writing from the beginning when EEPROM is full
}
EEPROM.put(addr, receivedValue);
addr += sizeof(receivedValue);
if (addr >= EEPROM_SIZE) {
addr = 0; // Start writing from the beginning when EEPROM is full
}
Serial.print("Received Timestamp: ");
printTime(currentTimestamp); // Display time in HH:MM:SS format
Serial.println(" Received Value: " + String(receivedValue));
}
if (!displayInProgress && millis() - lastDisplayTime >= timeRefreshDisplay) {
displayInProgress = true;
lastDisplayTime = millis();
// Call the display function
displayEEPROMData();
displayInProgress = false;
}
}
Maybe that will work...
It didn't.
What does the program not do that you want it to do?
What does the program do that you do not want it to do?
"It didn't work" is not a very helpful problem statement for those of us trying to work with you.
now I'm told the data is natural numbers 0-60
Or maybe it is newline?
Are you now certain that you will be receiving the ascii characters of a number between 0 and 60 terminated by a new line? Is that is the case, your .readBytesUntil( ) routine should work fine with that format.
If the received Value is going to be limited to 0-60 it can fit into a byte, and you can save some eeprom space by storing the byte in one memory location instead of the int in two.
//int receivedValue = atoi(receivedData);
byte receivedValue = atoi(receivedData);
What are your issue with handling the time value the integer is received?
Same objective: read each natural number that comes in and save it in EEPROM with the time it was received.