I am using the Arduino IDE to to write a sketch that passes data saved in progmem to a function, the function then writes the progmem data to local array.
The code is below:
const uint8_t Data_3 [256] PROGMEM = {0x11, 0x39.....}
void setup() {
Serial.begin(57600);
Data(Data_3, 0x00, 256);
}
void loop() {
}
void Data(const uint8_t *data, uint8_t bank, uint16_t bytes) {
uint8_t buff1 [256];
buff1[0] = data[0];
Serial.println(buff1[0],HEX); // <--Works fine prints the correct value
for ( uint16_t x = 0; x < bytes + 1; x++ ) {
buff1[x] = data[x];
Serial.println(buff1[x],HEX); // <--Just prints garbage
}
}
When I assign buff1[0] = data[0] and print the result the answer is correct. When I loop a print function with buff1[x] = data[x] I just get rubbish. Does anyone know the reason for this?
You have to use #include <avr/pgmspace.h> and Serial.print(pgm_read_byte(data+x)); otherwise it'll try to get data from the same address but from RAM, not from Flash memory.
Or copy into the buffer by memcpy_P(buff, data, bytes);
Related
I'm trying to get this Code for the AMT22 Encoder Using a ESP32C3-DevModule to work but the Arduino IDE is erroring me that "HSPI" is not declared in the scope any suggestions on what it should be declared as?
It also is Erroring for the line below
begin(_pinCLCK, _pinMISO, _pinMOSI, _pinSS);
but it should be pulling from the AMT22.h library those values.
#include "AMT22.h"
#include <stdlib.h>
#include <SPI.h>
SPIClass * AMT22::encoder = NULL; // this must be here -> see https://stackoverflow.com/questions/39336029/arduino-accessing-static-variable-in-the-classs-static-method
AMT22::AMT22(const byte CLCK,
const byte MISO,
const byte MOSI,
const byte SS) {
_pinCLCK = CLCK;
_pinMISO = MISO;
_pinMOSI = MOSI;
_pinSS = SS;
}
void AMT22::Begin() {
if (AMT22::encoder == NULL) {
AMT22::encoder = new SPIClass(HSPI);
AMT22::encoder -> setClockDivider(SPI_CLOCK_DIV32);
AMT22::encoder -> begin(_pinCLCK, _pinMISO, _pinMOSI, _pinSS); // SCLK, MISO, MOSI, SS
}
This is from the AMT22.h Library
private:
AMT22::Position getPositionSingle();
AMT22::Position getPositionMulti();
void setCSLine(uint8_t releaseLine);
uint8_t spiWriteRead(uint8_t sendByte, uint8_t releaseLine);
AMT22::Position position;
byte _pinMISO = 12;
byte _pinMOSI = 13;
byte _pinCLCK = 14;
byte _pinSS = 15;
// uninitalised pointers to SPI
objects
static SPIClass *encoder;
};
#endif
The code is intended to Get a Multiturn Function from the encoder- i.e. When the Motor spins the encoder will be able to serial print the amount of rotations counting upwards and downwards.
Appreciate your time.
I am trying to convert "String" read from serial port in serialEvent() of Arduino IDE to integer values with exact representation.
For eg, if String myString = 200 then int myInt should be 200.
I have been somewhat successful but unable to convert String to exact int representation beyond 255.
Solutions I have tried:
1) used .toInt() function in Arduino.
2) used "atoi" and "atol" functions.
3) Serial.parseInt() in loop().
All of these methods start recounting from 0 after every 255 values.
I can't use parseInt since it only works inside loop(). My application requires to store variable value permanently until another value is given through port. For this Arduino Due's flash memory has been used.
The memory storing code seems to work only inside serialEvent().
Code snippet is as below:
#include <stdlib.h>
#include <DueFlashStorage.h>
DueFlashStorage memory;
String x = " ";
int x_size;
int threshold;
void setup(){
Serial.begin(115200);
}
void loop{
Serial.println(memory.read(0));
}
void serialEvent(){
while(Serial.available()){
x = Serial.readStringUntil('\n');
x_size = x.length();
char a[x_size+1];
x.toCharArray(a, x_size+1);
threshold = atoi(a);
memory.write(0, threshold);
}
}
1) Function .toInt() returns LONG and you want INT (I don't know why honestly but it is in documentation)... you need to cast it like this (tried on Arduino ATMEGA and it worked):
#include <stdlib.h>
String x = "1000";
int x_ = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
x_ = (int) x.toInt();
Serial.println(x_);
delay(1000);
}
2) I’m not professional ... but serilEvent() is really old way of doing things and it isn't recommended to use it. You can do it "manually" in the loop() function.
You're only converting 1 character a time, that's why the limit is 255.
If you're not doing anything else, you could stay in a serial.read-loop until all characters are read. For example:
void loop() {
if(Serial.available()) {
byte count = 0;
char number[10]; // determine max size of array
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == '\n') {
wait = false; // exit while loop
}
count++;
}
}
int threshold = atoi(number);
memory.write(0, threshold);
}
}
For the lack of a good function in Arduino IDE for char/String type to int type conversion (has a limit of 255), I wrote my own conversion code which seems to work perfectly.
int finalcount=0;
void setup(){
Serial.begin(115200);
}
void loop(){
if(Serial.available()) {
int count = 0;
char number[5]; // determine max size of array as 5
bool wait = true;
while(wait) { // stay in this loop until newline is read
if(Serial.available()) {
number[count] = Serial.read();
if (number[count] == '\n') {
finalcount = count; //max array size for integer; could be less than 5
wait = false; // exit while loop
}
count++;
}
}
int val[finalcount]; //array size determined for integer
int placeValue;
int finalval[finalcount];
int temp=0;
int threshold;
for(int i = 0; i<finalcount; i++){
val[i] = (int)number[i]-48; //convert each char to integer separately
placeValue = pow(10,(finalcount-1)-i); //calculate place value with a base of 10
finalval[i] = val[i]*placeValue; //update integers with their place value
temp += finalval[i] ; //add all integers
threshold = temp; //resulting number stored as threshold
}
Serial.println(threshold); //prints beyond 255 successfully !
}
}
I solved the problem using highByte and lowByte functions of Arduino. Works flawlessly.
#include <DueFlashStorage.h>
DueFlashStorage m;
byte a1,a2;
int val;
void setup() {
Serial.begin(115200); //start the serial communication
}
void loop()
{
if (Serial.available()>0)
{
val = Serial.parseInt(); //read the integer value from series
if(val>0){
a1 = highByte(val); //get the higher order or leftmost byte
a2 = lowByte(val); //get the lower order or rightmost byte
m.write(0,a1); //save in arduino due flash memory address 0
m.write(1,a2); //save in arduino due flash memory address 1
}
int myInteger;
myInteger = (m.read(0)*256)+m.read(1); //convert into the true integer value
Serial.println(myInteger);
}
Below is a code ran on an ATmega328P. It's supposed to send "abcdef" to my computer every second. However, it sent me only "ab" every second. What is wrong here?
#include <avr/io.h>
#include <util/delay.h>
void USART_transmit(unsigned char data);
void print(const unsigned char *buffer, size_t n);
void print(const char* str);
int main(void) {
// Serial.begin(115200)
UCSR0B |= (1<<TXEN0);
UBRR0L = 8;
while(1){
// Serial.write(i)
print("abcdef");
_delay_ms(1000);
}
}
void USART_transmit(const uint8_t data) {
/* wait for empty transmit buffer */
while (!UCSR0A & (1<<UDRE0));
UDR0 = data;
}
void print(const uint8_t *buffer, size_t n) {
while(n--){
USART_transmit(*buffer++); //**
}
}
void print(const char *str) {
if(strlen(str) != 0) print((const uint8_t *) str, strlen(str));
}
The code resulted in:
ababababababababababab...
Changing from USART_transmit(*buffer++); to USART_transmit(n + 48); (+48 to convert to char) resulted in:
5454545454545454545454545454...
So I guess the loop shouldn't be stopping?
The "data register empty" check is wrong.
while (!UCSR0A & (1<<UDRE0));
should be
while (!(UCSR0A & (1 << UDRE0)));
In your case, the check is not blocking until the buffer is empty. I think one byte is buffered in the USART output buffer and one byte is pending in UDR. Every additional byte is then discarded, this is why you see only "ab".
I'm using ArduinoJSON to write a couple of data points to my EEPROM on Arduino Uno. I'm running into a problem with getGroundedPR where I need to convert a uint8_t to a char to pass retrieved data into my JSON parser.
This is my first time using EEPROM so I'm willing to bet there's a better way to do this. Should I continue to use JSON or is there a better way? I'm being cautious of the 10k write limit (give or take) on the EEPROM.
the EEPROM read/write is commented out until I have my process nailed down
void IMUController::setGroundedPR(double p, double r) {
Serial.print("Setting IMU ground: ");
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["pitch"] = p;
root["roll"] = r;
root.printTo(Serial);
char buffer[256];
root.printTo(buffer, sizeof(buffer));
Serial.println();
// EEPROM.write(EEPROM_ADDRESS_IMU_GROUNDED, buffer);
}
double* IMUController::getGroundedPR() {
double ret[2] = {0, 0};
StaticJsonBuffer<200> jsonBuffer;
uint8_t json_saved = EEPROM.read(EEPROM_ADDRESS_IMU_GROUNDED);
char json[] = "asdf"; // convert json_saved to char here
JsonObject& root = jsonBuffer.parseObject(json);
if(!root.success()) {
// return the result
ret[0] = (double)root["pitch"];
ret[1] = (double)root["roll"];
return ret;
}
return ret;
}
The EEPROM functions read() and write() only deal with a single character. You need to use put() and get() to deal with arrays.
char buffer[256];
root.printTo(buffer, sizeof(buffer));
EEPROM.put(EEPROM_ADDRESS_IMU_GROUNDED, buffer);
And to read it back:
char json[256];
EEPROM.get(EEPROM_ADDRESS_IMU_GROUNDED, json);
JsonObject& root = jsonBuffer.parseObject(json);
You need to take care with he array sizes though, the EEPROM functions will get and put the number of bytes in the array (256). The string should be null terminated so the extra bytes shouldn't cause a problem.
I'm attempting to send 8-bit byteArrays to an rfduino.
In the sketch, I got
void RFduinoBLE_onReceive(char *data, int len) {
int firstbyte = data[0];
Serial.println(firstbyte)
}
This works fine if the firstbyte is over 32. But if I'm sending a byteArray of [13, ...], firstbyte is parsed as 0.
I think I understand why (?):
RFduinoBLE parses incoming data as characters before sending it to this function, and bytes up to 32 are empty string.
So my question is: how can I use the RFduinoBLE-onReceive to read bytearrays with values below 32?
The following seems to work just fine:
void RFduinoBLE_onReceive(char *data, int length) {
uint8_t firstbyte = data[0];
}
or for arrays
uint8_t getData[20];
void RFduinoBLE_onReceive(char *data, int length) {
for (i = 0; i < length; i++) {
getData[i] = data[i];
}
}
Not quite sure what went right/wrong where, but I suspect either using int firstbyte instead of uint8_t firstbyte or casting uint8_t firstbyte = (uint8_t) data[0] did something I didn't expect.