How to write 16bit integer to SRAM via Arduino? - arduino

The base of the problem: I have an Arduino Due and a MPU6050 accelerometer and an 23lcv512. MPU gives me 16bit signed integer. I would like to save the datas to the SRAM and after the measurement read them back and via Serial send it to PC. Sending to PC is not a problem. The problem is that this SRAM has 128k pcs 8bit address. My numbers are 16 bit. I can't write them directly. Here is my code. I tested the RAM with this code:
`
void loop() {
int i = 0;
Serial.print("Write Byte: ");
for (i = 0; i < 70000; i++) {
//Serial.print("Write Byte: ");
//Serial.print(i);
//Serial.println();
SRAM.writeByte(START_ADDRESS, i);
START_ADDRESS = START_ADDRESS + 1;
}
Serial.print("Write End");
i = 0;
START_ADDRESS = 0;
for (i = 0; i < 300; i++) {
Serial.print("Read Byte: ");
Serial.print(SRAM.readByte(START_ADDRESS));
Serial.println();
Serial.println();
START_ADDRESS = START_ADDRESS + 1;
delay(100);
}
}`
I added the 23LC library. If it's run reads back the numbers from the RAM but after 255 it starts to read 0 again. I know why does it happen. But I don't know howto solve the problem.
I tried to use the writeBlock command but it only works for me with char variables. Char variable requires more space than integers. I have not too much.
Is there anyone who can write a sample code which can write 16 bit signed integer to sram?

I've commented the most obvious problems in your original code below:
void loop() {
int i = 0;
Serial.print("Write Byte: ");
for (i = 0; i < 70000; i++) { // since i is a 16bit int, 70,000 is out of range.
SRAM.writeByte(START_ADDRESS, i); // cool you wrote 1 byte, where is the other write?
START_ADDRESS = START_ADDRESS + 1; // try to keep all caps names for constants.
// this will make your code easier to read, trust me!
}
Serial.print("Write End");
i = 0;
START_ADDRESS = 0;
for (i = 0; i < 300; i++) {
Serial.print("Read Byte: ");
Serial.print(SRAM.readByte(START_ADDRESS)); // you read 1 byte, you can't expect a 16 bit
// value out of that.
Serial.println();
Serial.println();
START_ADDRESS = START_ADDRESS + 1;
delay(100);
}
}
Here's a more sound approach, it stores unsigned ints, but that can easily be changed to signed ints.
#define SRAM_SIZE (128UL << 10) // we have 128K of SRAM available.
// The U and L make this value an unsigned long.
// ALWAYS use unsigned values for addresses.
void loop()
{
Serial.print(F("Writing sequential numbers into SRAM...")); // _always_ store string constants in flash.
// save your RAM for more interesting stuff.
for (unsigned long i = 0; i < SRAM_SIZE; i += 2) // filling SRAM
{
// this is the (truncated from 0-65535) value we'll write.
unsigned int value = static_cast<unsigned int>(i & 0xFFFF);
SRAM.writeByte(i, value & 0xFF); // write lowest 8 bits
SRAM.writeByte(i + 1, (value >> 8) & 0xFF); // write next 8 bits.
}
Serial.println(F("done."));
// read back
Serial.println(F("SRAM contents (16-bits unsigned values):"));
for (unsigned long i = 0; i < SRAM_SIZE; i += 2) // reading all SRAM in 16-bit chunks.
{
Serial.print(i, HEX);
Serial.print(F(": "));
// read two consecutive bytes and pack them into a 16-bit integer.
unsigned int value = SRAM.readByte(i) + (static_cast<unsigned int>(SRAM.readByte(i+1)) << 8); // the cast is necessary.
Serial.println(value);
}
delay(100);
}

Related

Write String to permanent flash memory of Arduino ESP32

I want to write some text into the flash memory of an Arduino ESP32. It works kinda but not as I want it to.
void writeString(const char* toStore, int startAddr) {
int i = 0;
for (; i < LENGTH(toStore); i++) {
EEPROM.write(startAddr + i, toStore[i]);
}
EEPROM.write(startAddr + i, '\0');
EEPROM.commit();
}
My call
writeString("TEST_STRING_TO_WRITE", 0);
only writes TEST into the memory. I do not understand why. Is that because of the _? Or am I missing something different?
Here is the used LENGTH macro
#define LENGTH(x) (sizeof(x)/sizeof(x[0]))
and the method I use to read the string from the memory again (which seems to work correctly):
String readStringFromFlash(int startAddr) {
char in[128];
char curIn;
int i = 0;
curIn = EEPROM.read(startAddr);
for (; i < 128; i++) {
curIn = EEPROM.read(startAddr + i);
in[i] = curIn;
}
return String(in);
}
Where on earth did you get that LENGTH macro from? It’s surreal.
sizeof will not do what you want here. It’s a compile-time function that computes the storage requirements of its argument. In this case it should return the length in bytes of a character pointer, not the string it points to.
You want to use strlen(), assuming your char* is a properly terminated C string. Add one to make sure the ‘\0’ at the end gets stored, too.
#define LENGTH(x) (strlen(x) + 1)
Below is the code to demonstrate the storing as well as retrieving of the string ssid in the EEPROM (permanent storage).
#include "EEPROM.h"
int addr = 0;
#define EEPROM_SIZE 64
// the sample text which we are storing in EEPROM
char ssid[64] = "CARNIVAL OF RUST";
void setup() {
Serial.begin(115200);
Serial.println("starting now...");
if (!EEPROM.begin(EEPROM_SIZE)) {
Serial.println("failed to init EEPROM");
while(1);
}
// writing byte-by-byte to EEPROM
for (int i = 0; i < EEPROM_SIZE; i++) {
EEPROM.write(addr, ssid[i]);
addr += 1;
}
EEPROM.commit();
// reading byte-by-byte from EEPROM
for (int i = 0; i < EEPROM_SIZE; i++) {
byte readValue = EEPROM.read(i);
if (readValue == 0) {
break;
}
char readValueChar = char(readValue);
Serial.print(readValueChar);
}
}
void loop() {
}

How to check for a gap between serial data

I'm working on an interface that reads serial data from a single wire bus on a car (BMW IBUS). I'm using an Microchip MCP2025 LIN bus transceiver chip to convert the single line bus to regular Rx/Tx to feed into the hardware serial pins (0 & 1) of an Arduino (Nano V3).
BMW's IBUS protocol uses Serial 8E1 at 9600 baud. Messages are variable length (between 5 and 37 bytes) Bus messages are separated by a pause of around 11 milliseconds (considerably longer than the bus high time when receiving) and I need to use this gap to detect the end of one message and the beginning of the next.
1st byte is the Source ID,
2nd byte is length of the packet excluding the first two bytes (source & length),
3rd byte is the destination ID,
4th byte onwards is the actual data,
Last byte is the checksum
Checksum is generated by XOR of the entire packet excluding the checksum itself.
My problem is that I don't know how to measure the bus idle time between messages. I think I can use bitRead(PIND,0) to tell when the bus is idle (high), but I'm not sure how to time this and go and process the message after a suitable time has passed.
I'm currently using the following code to read messages from the IBUS. It works for the most part, but gets out of sync when connected to the car. It's doesn't really know when messages have finished, but relies on the second byte of each message (the length byte) to know how many bytes to read in. As long as it reads the length byte correctly, it's fine, but if it gets out of sync, and the length byte is wrong, it reads in the wrong number of bytes and eventually overruns the array and the Arduino resets. If I can detect the idle time between messages I will know for sure that I have a complete message.
void ReadIBUS()
{
boolean inSTATE = 0;
byte IBUSbyte[40];
while(Serial.available() > 0 && inSTATE == 0 )
{
IBUSbyte[0] = Serial.read(); //read source byte
while (inSTATE == 0)
{
if(Serial.available() > 0)
{
IBUSbyte[1] = Serial.read(); //read length byte
inSTATE = 1;
}
delay(10);
}
inSTATE == 0;
LENGTH = IBUSbyte[1];
int i = 2;
while(i <= LENGTH + 1)
{
if(Serial.available() > 0)
{
IBUSbyte[i] = Serial.read();
i++;
delay(10);
}
}
checksumBYTE = 0;
byteSTATE = 0;
for (int i = 0; i < LENGTH + 1; i++){
checksumBYTE ^= IBUSbyte[i];
}
if (IBUSbyte[LENGTH + 1] == checksumBYTE){
for(int i = 0; i <= LENGTH + 1; i++)
{
mySerial.print(IBUSbyte[i], HEX);
mySerial.print(" ");
}
mySerial.println();
}
else {
debug();
inSTATE = 0;
byteSTATE = 0;
}
}
}
First off, delay is rarely a good thing to use. In this case, you can use millis to measure how long it is between characters, but only if you lose the delay:
void ReadIBUS()
{
byte IBUSbyte[40];
do {
// First, make sure we're between frames, in the quiet interval
uint32_t last_rx = millis();
while (millis() - last_rx < 5) {
// Hasn't been long enough, see if more chars are coming
if (Serial.available()) {
Serial.read(); // throw away partial frame chars
last_rx = millis();
}
}
// Haven't received any chars for a while, we must be
// between frames. Now wait for a frame.
while (!Serial.available())
; // waiting...
IBUSbyte[0] = Serial.read(); //read source byte
while (!Serial.available())
; // waiting...
IBUSbyte[1] = Serial.read(); //read length byte
LENGTH = IBUSbyte[1];
// Check the LENGTH to make sure it's not bogus. If it is, try again.
} while (LENGTH > sizeof(IBUSbyte)-1);
// LENGTH is reasonable, wait for the payload
uint8_t bytes_received = 2;
while (bytes_received <= LENGTH + 1) {
if (Serial.available()) {
IBUSbyte[ bytes_received++ ] = Serial.read(); // read frame payload byte
}
}
// All here, verify the checksum
checksumBYTE = 0;
for (int i = 0; i < LENGTH + 1; i++) {
checksumBYTE ^= IBUSbyte[i];
}
if (IBUSbyte[LENGTH + 1] == checksumBYTE) {
for(int i = 0; i <= LENGTH + 1; i++) {
mySerial.print(IBUSbyte[i], HEX);
mySerial.print(" ");
}
mySerial.println();
} else {
debug();
}
}
And the state variables are no longer needed.
BTW, this routine "blocks" the rest of the program from doing anything until a complete frame is received. It should probably be rewritten so that it is called frequently (like from loop), and last_rx and bytes_received are remembered across calls. It could return true when a complete frame has been received. This'll work, it's just sub-optimal because it blocks anything else from happening, except interrupts.

Arduino code weird return with Serial.read()

Having issues with the Serial.read() command on my Arduino code. I have it connected to two 74HC595's shift registers connected to LED's.
I check if there is Serial data, then read two bytes. Then pass these bytes to a method that shifts them both out. When I check the bytes with Serial.print to print them out to the serial moniter I get for example
49
255
50
255
Why am I getting the two 255's I have read the documentation on arduino.cc and it says it reads a single byte only. Any ideas?
The end goal is to read two bytes on the serial line and shift them out to the shift reg's IE is the byte values of decimal 5 & 6 were passed the 1st 3rd LED's would light on one shift register then the 2nd and 3rd would on the other shift register
const int dataPin = 8;
const int latchPin = 9;
const int clockPin = 10;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
byte low = Serial.read();
byte high = Serial.read();
Serial.println(low);
Serial.println(high);
sendBytes(low,high);
}
}
void sendBytes(byte l, byte h) {
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,MSBFIRST,l);
shiftOut(dataPin,clockPin,MSBFIRST,h);
digitalWrite(latchPin,HIGH);
}
if (Serial.available() > 0) {
byte low = Serial.read();
byte high = Serial.read();
//...
This is a bug in your code. Very likely to trip, serial ports are not that fast. So high odds that Serial.available() only returns 1. You'll read the low byte okay but Serial.read() will then return -1 if there is no data to read. Which makes high equal to 0xff. The simple fix is:
if (Serial.available() >= 2)
I had the same problem reading from a program...
I had luck both letting the code loop until filled...
and before taking on new Serial data I flush the serial to get the latest bytes
While(Serial.read() != -1); //clears data in the PC Serial Port
Here's what it looks like all put together
int i = 0;
byte bytes[3];
interval = 150; //allows for this amount of time to read from serial
long previousMillis = 0;
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis < interval && i < 2) {
if(Serial.available() > 0) {
bytes[i] = Serial.read();
i++; }
}
if(currentMillis - previousMillis > 1000) { //waits 1 second to get new serial data
previousMillis = currentMillis; //resets the timer
i = 0;
While(Serial.read() != -1); //clears data in the PC Serial Port
}

Arduino Code not executing after Wire.endTransmission line

I am working on a project, syncing Nintendo Nunchuk with Arduino. I found a code online for the same from http://letsmakerobots.com/node/5684
Here, is the code
#include <Wire.h>;
void setup(){
Serial.begin(19200);
nunchuck_setpowerpins();
nunchuck_init();
Serial.print("Nunchuck ready\n");
}
void loop(){
nunchuck_get_data();
nunchuck_print_data();
delay(1000);
}
//======================================================================================================================================================================================================//
//Do not modify!!!!!!!!
//======================================================================================================================================================================================================//
//
// Nunchuck functions
//
static uint8_t nunchuck_buf[6]; // array to store nunchuck data,
// Uses port C (analog in) pins as power & ground for Nunchuck
static void nunchuck_setpowerpins()
{
#define pwrpin PORTC3
#define gndpin PORTC2
DDRC |= _BV(pwrpin) | _BV(gndpin);
PORTC &=~ _BV(gndpin);
PORTC |= _BV(pwrpin);
delay(100); // wait for things to stabilize
}
// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
void nunchuck_init()
{
Wire.begin(); // join i2c bus as master
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.send(0x40); // sends memory address
Wire.send(0x00); // sends sent a zero.
Wire.endTransmission(); // stop transmitting
}
// Send a request for data to the nunchuck
// was "send_zero()"
void nunchuck_send_request()
{
Wire.beginTransmission(0x52); // transmit to device 0x52
Wire.send(0x00); // sends one byte
Wire.endTransmission(); // stop transmitting
}
// Receive data back from the nunchuck,
// returns 1 on successful read. returns 0 on failure
int nunchuck_get_data()
{
int cnt=0;
Wire.requestFrom (0x52, 6); // request data from nunchuck
while (Wire.available ()) {
// receive byte as an integer
nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.receive());
cnt++;
}
nunchuck_send_request(); // send request for next data payload
// If we recieved the 6 bytes, then go print them
if (cnt >= 5) {
return 1; // success
}
return 0; //failure
}
// Print the input data we have recieved
// accel data is 10 bits long
// so we read 8 bits, then we have to add
// on the last 2 bits. That is why I
// multiply them by 2 * 2
void nunchuck_print_data()
{
static int i=0;
int joy_x_axis = nunchuck_buf[0];
int joy_y_axis = nunchuck_buf[1];
int accel_x_axis = nunchuck_buf[2]; // * 2 * 2;
int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;
int z_button = 0;
int c_button = 0;
// byte nunchuck_buf[5] contains bits for z and c buttons
// it also contains the least significant bits for the accelerometer data
// so we have to check each bit of byte outbuf[5]
if ((nunchuck_buf[5] >> 0) & 1)
z_button = 1;
if ((nunchuck_buf[5] >> 1) & 1)
c_button = 1;
if ((nunchuck_buf[5] >> 2) & 1)
accel_x_axis += 2;
if ((nunchuck_buf[5] >> 3) & 1)
accel_x_axis += 1;
if ((nunchuck_buf[5] >> 4) & 1)
accel_y_axis += 2;
if ((nunchuck_buf[5] >> 5) & 1)
accel_y_axis += 1;
if ((nunchuck_buf[5] >> 6) & 1)
accel_z_axis += 2;
if ((nunchuck_buf[5] >> 7) & 1)
accel_z_axis += 1;
Serial.print(i,DEC);
Serial.print("\t");
Serial.print("joy:");
Serial.print(joy_x_axis,DEC);
Serial.print(",");
Serial.print(joy_y_axis, DEC);
Serial.print(" \t");
Serial.print("acc:");
Serial.print(accel_x_axis, DEC);
Serial.print(",");
Serial.print(accel_y_axis, DEC);
Serial.print(",");
Serial.print(accel_z_axis, DEC);
Serial.print("\t");
Serial.print("but:");
Serial.print(z_button, DEC);
Serial.print(",");
Serial.print(c_button, DEC);
Serial.print("\r\n"); // newline
i++;
}
// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char nunchuk_decode_byte (char x)
{
x = (x ^ 0x17) + 0x17;
return x;
}
// returns zbutton state: 1=pressed, 0=notpressed
int nunchuck_zbutton()
{
return ((nunchuck_buf[5] >> 0) & 1) ? 0 : 1; // voodoo
}
// returns zbutton state: 1=pressed, 0=notpressed
int nunchuck_cbutton()
{
return ((nunchuck_buf[5] >> 1) & 1) ? 0 : 1; // voodoo
}
// returns value of x-axis joystick
int nunchuck_joyx()
{
return nunchuck_buf[0];
}
// returns value of y-axis joystick
int nunchuck_joyy()
{
return nunchuck_buf[1];
}
// returns value of x-axis accelerometer
int nunchuck_accelx()
{
return nunchuck_buf[2]; // FIXME: this leaves out 2-bits of the data
}
// returns value of y-axis accelerometer
int nunchuck_accely()
{
return nunchuck_buf[3]; // FIXME: this leaves out 2-bits of the data
}
// returns value of z-axis accelerometer
int nunchuck_accelz()
{
return nunchuck_buf[4]; // FIXME: this leaves out 2-bits of the data
}
When I write, Serial.Println("End"), in the line after Wire.endTransmission(); in function nunchuck_init(), it does not display on Serial Monitor.
Also, it does not display Nunchuck ready on Serial Monitor since it is written after nunchuck_init() has been called.
I am working on Arduino 0023, Windows 7.
A existing problem with the stock Arduino Wire library is that there is no timeout.
It is possible for the endTransmission function to hang the microcontroller in different scenarios.
This issue has been discussed in several other forums, and the best solution I've found so far is to use an alternate library.
The Arduino I2C Master Library by Wayne Truchsess
http://www.dsscircuits.com/index.php/articles/66-arduino-i2c-master-library
With proper timeout, it fixed the problem on my system reading the MMA7455 accelero
In the source code provided, there's an example where it shows how the same piece of program is done using Wire vs the I2C Master Library.
You can use that example to easily modify your code to adopt the new library.

Arduino : Check byte array for chars one at a time

I communicate with Arduino via Serial using a program that sends a series of bytes.
In order for the Arduino to realize it is receiving a message rather than junk, I have tagged the start of my byte array with the chars 'S' 'T' 'A' 'R' 'T'. After this will eventually follow a series of bytes that will be assigned to internal variables (not yet implemented).
The Arduino must read each byte sequentially and compare it to the byte array and if all are present in the correct order it will continue with the next part of the program, otherwise it will should discard current byte and wait for more bytes to arrive.
I am trying to implement it in the most efficient and readable way rather than using a series of nested if statements.
So far I have got:
byte inByte = 0;
byte handShake[] = {'S','T','A','R','T'};
void setup() {
Serial.begin(9600);
}
void loop()
{
while (Serial.available())
{
for (int x =0; x < sizeof(handShake) ; x++)
{
inByte = Serial.read();
Serial.println(x);
if (inByte == handShake[x])
{
if (x == (sizeof(handShake)-1)) {setArduino();}
}
else break;
}
}
}
void setArduino () {
Serial.println("Ready To Set Parameters");
}
This however doesn't seem to get past the second byte and I'm not sure why.
Worked it out :
Here is the answer:
byte inByte = 0;
char handShake[] = {'S','T','A','R','T'};
void setup() {
Serial.begin(9600);
}
void loop()
{
while (Serial.available())
{
for (int x =0; x < sizeof(handShake) ; x++)
{
inByte = Serial.read();
Serial.println(x);
if (inByte == handShake[x])
{
if (x == (sizeof(handShake)-1)) {setArduino();}
while(!Serial.available()) {delay(1);}
}
else {break;}
}
}
}
void setArduino () {
Serial.println("Ready To Set Parameters");
}
This may not be the most efficient way perhaps, but I can't see a problem with it currently.
Better answer : This allows the rest of the loop to iterate while waiting for the message to finish and if the full handshake message isn't received the counter will reset.
byte inByte = 0;
char handShake[] = {'S','T','A','R','T'};
int messageIndex = 0;
void setup() {
Serial.begin(9600);
}
void loop()
{
while (Serial.available())
{
inByte = Serial.read();
Serial.println(messageIndex);
if (inByte == handShake[messageIndex])
{
messageIndex++;
if (messageIndex == sizeof(handShake)) {messageIndex = 0; setArduino();}
}
else {messageIndex=0;}
}
// Other code while waiting for message to finish
Serial.println("tick");
}
void setArduino () {
Serial.println("Ready To Set Parameters");
}
You could try to calculate your message. CRC is old and good solution. I use it and it works perfect for me. I am not sure what kind of device are you communicating with.
//define
const uint32_t Polynomial = 0xEDB88320;
const uint16_t NumBytes = 256;
uint8_t data[NumBytes];
/// compute CRC32
uint32_t crc32_bitwise(const void* data, uint16_t length, uint32_t previousCrc32 = 0)
{
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
uint8_t* current = (uint8_t*) data;
while (length--)
{
crc ^= *current++;
for (uint8_t j = 0; j < 8; j++)
{
uint8_t lowestBit = crc & 1;
crc >>= 1;
if (lowestBit)
crc ^= Polynomial;
}
}
return ~crc; // same as crc ^ 0xFFFFFFFF
}
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
when you need to calculate CRC
uint32_t crc = crc32_bitwise(data_bytes, sizeof(data_bytes));
data_bytes is byte array.
Then you can get all settings or message in byte data[x] and calculate CRC. Then you can add CRC to the message and send message byte data[x+sizeof(CRC)]
P.S. Use byte instead of int. For ex. for(byte x =0; x<sizeof(handShake); x++)

Resources