esp32 modbus rtu hex to float convert - c++

I can send a request and get an response (modbus RTU frame) from the device (flow meter) but I cannot convert hex to float. Otherwise everything works fine and the way I want it. Does anyone know how to improve it in a simple way?
void loop() {
const char msg_reguest[] = {0x01, 0x04, 0x00, 0x08, 0x00, 0x02, 0xf0, 0x09};
delay(200);
int i;
int len=8;
Serial.println("WYSŁANA RAMKA");
for(i = 0 ; i < len ; i++){
Serial2.write(msg_reguest[i]);
Serial.print("[");
Serial.print(i);
Serial.print("]");
Serial.print("=");
Serial.print("Ox");
Serial.print(String(msg_reguest[i], HEX));
Serial.print(" ");
}
len = 0;
Serial.println();
Serial.println();
int a = 0;
while(Serial2.available())
{
ByteArray[a] = Serial2.read();
a++;
}
int b = 0;
String registros;
Serial.println("ODEBRANA RAMKA");
for(b = 3 ; b < a-2 ; b++){
Serial.print("[");
Serial.print(b);
Serial.print("]");
Serial.print("=");
Serial.print("Ox");
registros =String(ByteArray[b], HEX);
Serial.print(registros);
Serial.print(" ");
}
byte hexArray[] = "registros";
float value;
memcpy(&value, hexArray, sizeof(hexArray));
Serial.println(value);
}
the point is that I have an esp32, TTL rs485 and a flow meter with rs485. I download a frame each time with a different data value. I display the frame with the flow data in the serial monitor in the form of HEX. Esp32 are little Endian, so I want to change the order of numbers and write a function that will automatically convert to float. In the above code I try to do it but it doesn't work

Related

uint8 array passing value fail - only one uint8_t sent

I try to start a array in the header file
rs485.h
class RS485
{
public:
uint8_t off[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
void sendmsg(uint8_t* cmd);
};
rs485.cpp
void RS485::sendmsg(uint8_t* cmd)
{
//digitalWrite(ENTX_PIN, HIGH); // enable to transmit
Serial.println("sending message------------");
Serial2.write(cmd[0]);
Serial.println(cmd[0], HEX);
Serial2.write(cmd[1]);
Serial.println(cmd[1], HEX);
Serial2.write(cmd[2]);
Serial.println(cmd[2], HEX);
Serial2.write(cmd[3]);
Serial.println(cmd[3], HEX);
Serial2.write(cmd[4]);
Serial.println(cmd[4], HEX);
Serial2.write(cmd[5]);
Serial.println(cmd[5], HEX);
Serial2.write(cmd[6]);
Serial.println(cmd[6], HEX);
Serial2.write(cmd[7]);
Serial.println(cmd[7], HEX);
Serial.println("--------------------------");
}
main.cpp
void callback(char *topic, byte *payload, unsigned int length)
{
'''omit'''
if (cmd)
{
Serial.print("cmd: ");
Serial.println(cmd);
if (cmd == 700)
{
rs485.sendmsg(rs485.off);
}
else if (cmd == 701)
{
rs485.sendmsg(rs485.on);
}
'''omit'''
}
'''omit'''
}
complier have an error message of "too many initializer values".
When I try to use
uint8_t off[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
it build normally. The problem is when in use this variable in main.cpp and pass it to rs485.cpp only one element off[0] is pass normally.
rs485.sendmsg(rs485.off);
I have use serial print to check all value it can all print out but the rs485 cannot tx all char.
Serial2.write(cmd[0]);
Serial.println(cmd[0], HEX);
Serial2.write(cmd[1]);
Serial.println(cmd[1], HEX);
Serial2.write(cmd[2]);
Serial.println(cmd[2], HEX);
Serial2.write(cmd[3]);
Serial.println(cmd[3], HEX);
Serial2.write(cmd[4]);
Serial.println(cmd[4], HEX);
Serial2.write(cmd[5]);
Serial.println(cmd[5], HEX);
Serial2.write(cmd[6]);
Serial.println(cmd[6], HEX);
Serial2.write(cmd[7]);
Serial.println(cmd[7], HEX);
Any result for that?
add the wiring
gpio26 -->DE+RE
gpio21 -->DI
gpio25 -->RO
A member variable declared as
uint8_t off[] = { ... };
does not become an array with the number of elements in the initializer list, like when you declare a non-member variable. Instead, it then becomes a "flexible array" (a C thing that g++ enables by default in C++) - and flexible arrays can't have initializers, which is why you get "too many initializer values".
The correct way is therefore to specify the number of elements:
uint8_t off[8] = { ... };
I suggest that you send them all out at once and check how many that are actully written:
size_t written = Serial2.write(cmd, 8);
Serial.println(written);
This should display 8 if the sending code works.

Arduino CANBUS MCP2515 Extended ID Receive Filter Problem

I would like to read CANBUS output of a device, but instead of reading every message, I need to filter out all messages except "0x18DAF938" message.
I am using Cory J. Fowler's library.
I changed Extended_MaskFilter example code as below but still no success:
#include <mcp_can.h>
#include <SPI.h>
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
MCP_CAN CAN0(53); // Set CS to pin 10
void setup()
{
Serial.begin(115200);
if(CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_8MHZ) == CAN_OK) Serial.print("MCP2515 Init Okay!!\r\n");
else Serial.print("MCP2515 Init Failed!!\r\n");
pinMode(2, INPUT); // Setting pin 2 for /INT input
CAN0.init_Mask(0,1,0xFFFFFFFF); // Init first mask...
CAN0.init_Filt(0,1,0x18DAF938); // Init first filter...
Serial.println("MCP2515 Library Mask & Filter Example...");
CAN0.setMode(MCP_NORMAL); // Change to normal mode to allow messages to be transmitted
}
void loop()
{
if(!digitalRead(2)) // If pin 2 is low, read receive buffer
{
CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s)
Serial.print("ID: ");
Serial.print(rxId, HEX);
Serial.print(" Data: ");
for(int i = 0; i<len; i++) // Print each byte of the data
{
if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero
{
Serial.print("0");
}
Serial.print(rxBuf[i], HEX);
Serial.print(" ");
}
Serial.println();
}
}
I am using Arduino Mega2560 and NiRen MCP2515 module.
Help would be appreciated. Thanks.

STM32 Pin B0 works as input, but B1 doesn't

I am making a simple counter up/down using STM32F103C4, 2 buttons and a 7seg display, and the code is written in Keil uVision, from which the hex file is loaded into Proteus. The Counter Up part works perfectly, but the Counter Down part is just not registering any input. I have tried switching the pins and have come to the conclusion that the B0 pin is working but for some reason the B1 pin is not. I have searched all over, and asked many but I can't find a solution. Does this have to do with the special port B reset value?
Below is my code and a ss of the proteus scheme.
#include "stm32f10x.h" // Device header
int dispBroj[]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
int j = 0;
void reset()
{
for(int i = 0; i < 7; i++)
{
GPIOA->ODR &=~ (1<<i);
}
}
void cifre(int broj)
{
GPIOA->ODR |= dispBroj[broj];
}
int main(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
GPIOA->CRL |=GPIO_CRL_MODE;
GPIOA->CRL &=~GPIO_CRL_CNF;
GPIOB->CRL|=((1<<7)|(1<<3));
GPIOB->CRL &=~((1<<2)|(1<<1)|(1<<0)|(1<<4)|(1<<5)|(1<<6));
GPIOB->CRH|=((1<<7)|(1<<3));
GPIOB->CRH &=~((1<<2)|(1<<1)|(1<<0)|(1<<4)|(1<<5)|(1<<6));
while(1){
cifre(j%10);
if(GPIOB->IDR & GPIO_IDR_IDR0){
reset();
j++;
cifre(j%10);
while(GPIOB->IDR & GPIO_IDR_IDR0){
if(!GPIOB->IDR & GPIO_IDR_IDR0)
break;
}
}
if(GPIOB->IDR & GPIO_IDR_IDR1){
reset();
j--;
cifre(j%10);
while(GPIOB->IDR & GPIO_IDR_IDR1){
if(!GPIOB->IDR & GPIO_IDR_IDR1)
break;
}
}
}
}
My suspicion is that I declared the GPIO wrong.
Try using the definition for GPIO init provided:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1| GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //you have an external pulldown.
GPIO_Init(GPIOB, &GPIO_InitStructure);

Overcome Arduino memory limitations with multiple sensors

I have an Arduino Nano piggybacked on a ENC28j60 ethernet module. I have eight (8) DHT22 sensors (named A, B, C ... H ) and i want to write their temperature and humidity data to Pushingbox.
The program is working great with ONE sensor. So that's good. However when i un-remark (i.e. take out the //'s) for anything more than one sensor, yes even for ONE other sensor, it won't write anything at all.
The arduino IDE complier says:
Sketch uses 23824 bytes (77%) of program storage space. Maximum is 30720 bytes.
Global variables use 1870 bytes (91%) of dynamic memory, leaving 178 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.
FYI, If i un-remark just one other sensor it goes up +2% to 93% of dynamic memory and stops working. So i'm assuming its a memory problem. i have already removed all floats (and made integers *10 to keep one decimal place of accuracy), i need 8 instances of DHT so considered reducing the library size but the .h seems tiny and pretty lean already (within the .h file it even boasts: Very low memory footprint - Very small code. so i havent modified this or the .cpp.
The overall code i have written is not large, maybe there are some in-efficiencies there, but i can't see that it is going to make anything near the amount of memory saving needed for the next 7 sensors.
The full arduino code (written for all 8 sensors, with 'ghosted' bits for 4 sensors and in use only working for one sensor) is below:
#include "DHTesp.h"
//#include <SPI.h>
#include <UIPEthernet.h>
DHTesp dhtA;
//DHTesp dhtB;
//DHTesp dhtC;
//DHTesp dhtD;
//DHTesp dhtE;
//DHTesp dhtF;
//DHTesp dhtG;
//DHTesp dhtH;
const int ledPin = LED_BUILTIN;
int ledState = LOW;
int interval = 10; // this is the number of seconds between reads (120=2mins)
int numReads = 5; // Number of reads between posting to google docs.
int multFact = 10; // multiplication factor 10 = 1 dec. place 100 = 2 dec places
byte mac[] = {0xBE, 0xEF, 0xDE, 0xAD, 0xDE, 0xAD }; //Ethernet shield MAC. Andy's working {0xBE, 0xEF, 0xDE, 0xAD, 0xDE, 0xAD}
byte ip[] = { 192,168,1,12 }; // Arduino device IP address
char devid [] = "vCE3D036xxxxxxxx"; // Gsheets device ID from Pushingbox ('x's for privacy:)
char server[] = "api.pushingbox.com";
EthernetClient client;
void setup()
{
Serial.begin(9600);
Serial.println ("RESTART");
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Trying to connect...");
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
while(true);
}
else{
Serial.print("OK, connected. Ethernet ready. ");
// print the Ethernet board/shield's IP address:
Serial.print("IP address: ");
Serial.println(Ethernet.localIP());
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println();
//Serial.println("A-Stat\t\tA-Temp (C)\tA-humdid%\tA-HeatI (C)\tB-Stat\t\tB-Temp (C)\tA-humdid%\tB-HeatI (C)");
Serial.println("\t\t\t\tt-A\th-A\tt-B\th-B\tt-C\th-C\tt-D\th-D\tt-E\th-E\tt-F\th-F\tt-G\th-G\tt-H\th-H");
//hey dB for some reason the Ethernet sheild uses pin D2 :( and pins 10,11,12,13
// https://arduinodiy.wordpress.com/2013/04/07/connect-an-enc28j60-ethernet-module-to-an-arduino/
// assign data pins
dhtA.setup(3);
//dhtB.setup(4);
//dhtC.setup(5);
//dhtD.setup(6);
//dhtE.setup(7);
//dhtF.setup(8);
//dhtG.setup(9);
//dhtH.setup(10); //watchout! i think Ethernet uses this pin too?
pinMode(ledPin, OUTPUT);
//end of void setup
}
void loop()
{
int Ahumid = 0; int Atemp = 0;
int Bhumid = 0; int Btemp = 0;
int Chumid = 0; int Ctemp = 0;
int Dhumid = 0; int Dtemp = 0;
//int Ehumid = 0; int Etemp = 0;
//int Fhumid = 0; int Ftemp = 0;
//int Ghumid = 0; int Gtemp = 0;
//int Hhumid = 0; int Htemp = 0;
int j=0;
for (j = 1; j <= numReads ; j++ ) {
int p = 0;
for (p=1; p <= interval ; p++) {
delay (1000);
// swap the led state
if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; }
Serial.print (p); //show the seconds passing
Serial.print (",");
digitalWrite(ledPin, ledState);
}
Serial.print (" Reading");
Atemp += dhtA.getTemperature()*multFact; Ahumid += dhtA.getHumidity()*multFact;
//Btemp += dhtB.getTemperature()*multFact; Bhumid += dhtB.getHumidity()*multFact;
//Ctemp += dhtC.getTemperature()*multFact; Chumid += dhtC.getHumidity()*multFact;
//Dtemp += dhtD.getTemperature()*multFact; Dhumid += dhtD.getHumidity()*multFact;
// print the readings
//Serial.print(dhtA.getStatusString());
Serial.print("\t"); Serial.print(Atemp);
Serial.print("\t"); Serial.print(Ahumid);
Serial.print("\t"); Serial.print(Btemp);
Serial.print("\t"); Serial.print(Bhumid);
Serial.print("\t"); Serial.print(Ctemp);
Serial.print("\t"); Serial.print(Chumid);
Serial.print("\t"); Serial.print(Dtemp);
Serial.print("\t"); Serial.print(Dhumid);
Serial.println();
// and so here endeth 'j', the number of reads
}
Serial.print ("Avg...");
Atemp = Atemp/numReads; Ahumid = Ahumid/numReads;
Btemp = Btemp/numReads; Bhumid = Bhumid/numReads;
Ctemp = Ctemp/numReads; Chumid = Chumid/numReads;
Dtemp = Dtemp/numReads; Dhumid = Dhumid/numReads;
// print the averages so we can see what it is going to send
Serial.print("\t\t\t");
Serial.print("\t"); Serial.print(Atemp); Serial.print("\t"); Serial.print(Ahumid);
Serial.print("\t"); Serial.print(Btemp); Serial.print("\t"); Serial.print(Bhumid);
Serial.print("\t"); Serial.print(Ctemp); Serial.print("\t"); Serial.print(Chumid);
Serial.print("\t"); Serial.print(Dtemp); Serial.print("\t"); Serial.print(Dhumid);
Serial.println();
Serial.print ("Prep for upload... ");
if (client.connect(server, 80))
{
Serial.print("Connected OK ... writing...");
client.print("GET /pushingbox?devid=");
client.print(devid);
client.print("&tempA="); client.print(Atemp);
client.print("&tempB="); client.print(Btemp);
client.print("&tempC="); client.print(Ctemp);
client.print("&tempD="); client.print(Dtemp);
client.print("&tempE=29&tempF=39&tempG=49&tempH=59");
//now humidity too
client.print("&humidA="); client.print(Ahumid);
client.print("&humidB="); client.print(Bhumid);
client.print("&humidC="); client.print(Chumid);
client.print("&humidD="); client.print(Dhumid);
client.print("&humidE=26&humidF=27&humidG=28&humidH=29");
client.print("&submit=Submit");
client.println(" HTTP/1.1");
client.println("Host: api.pushingbox.com");
client.println("Connection: close");
client.println();
Serial.println("written OK. & connection closed.");
Serial.println(); //Serial.println();
delay(1000); // maybe take this out to keep time stable?
client.stop();
}
else {
Serial.println("** NO CONNEX **"); Serial.println();
}
//here endeth void loop
}
Extra info (that i dont think is relevant, but maybe): IDE compiler also reports:
WARNING: library DHT_sensor_library_for_ESP32 claims to run on [esp32] architecture(s) and may be incompatible with your current board which runs on [avr] architecture(s).
Use the F macro for double-quoted string literal prints. Instead of this:
Serial.println ("RESTART");
or
client.print("GET /pushingbox?devid=");
... do this:
Serial.println ( F("RESTART") );
or
client.print( F("GET /pushingbox?devid=") );
This will easily save a bunch o' RAM.
I would also suggest using the single quoted literal for single characters, not the double quote:
Serial.print( '\t' );

Arduino uint8_t variables

I'm having trouble with some arduino code. im using an Ethernet tutorial code i found and some IR emitter and receiver code i found, and im trying to combine them.
http://www.ladyada.net/learn/sensors/ir.html
http://g33k.blogspot.com/2010/09/arduino-data-webserver-sample-web.html
Both codes work fine by themselves.
The code compiles but when i call the following void IRDetector() , it doesn't work. I have debugged it and so far ive found when i use the variable uint8_t or uint16_t (ive tried replacing them with ints and longs). Do i have to import and libraries to use uint8_t ? Any thoughts?
Any help would be appreciated.
uint16_t pulses[100][2]; // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we're storing
uint8_t highpulse, lowpulse; // temporary storage timing
void IRDetectCode(void)
{
while(true){
highpulse = lowpulse = 0; // start out with no pulse length
while (IRpin_PIN & (1 << IRpin)) {
// pin is still HIGH
// count off another few microseconds
highpulse++;
delayMicroseconds(RESOLUTION);
// If the pulse is too long, we 'timed out' - either nothing
// was received or the code is finished, so print what
// we've grabbed so far, and then reset
if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
Serial.print(" usec, ");
// printpulses();
//currentpulse=0;
return;
}
}
// we didn't time out so lets stash the reading
pulses[currentpulse][0] = highpulse;
// same as above
while (! (IRpin_PIN & _BV(IRpin))) {
// pin is still LOW
Serial.print(" usec, ");
lowpulse++;
delayMicroseconds(RESOLUTION);
if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
// printpulses();
// currentpulse=0;
return;
}
}
//pulses[currentpulse][1] = lowpulse;
// we read one high-low pulse successfully, continue!
currentpulse++;
}
}
void printpulses(void) {
Serial.println("\n\r\n\rReceived: \n\rOFF \tON");
for (uint8_t i = 0; i < currentpulse; i++) {
Serial.print(pulses[i][0] * RESOLUTION, DEC);
Serial.print(" usec, ");
Serial.print(pulses[i][1] * RESOLUTION, DEC);
Serial.println(" usec");
}
// print it in a 'array' format
Serial.println("int IRsignal[] = {");
Serial.println("// ON, OFF (in 10's of microseconds)");
for (uint8_t i = 0; i < currentpulse-1; i++) {
Serial.print("\t"); // tab
Serial.print(pulses[i][1] * RESOLUTION / 10, DEC);
Serial.print(", ");
Serial.print(pulses[i+1][0] * RESOLUTION / 10, DEC);
Serial.println(",");
}
Serial.print("\t"); // tab
Serial.print(pulses[currentpulse-1][1] * RESOLUTION / 10, DEC);
Serial.print(", 0};");
}
The uint8_t is a unsigned integer on 8 bits. In Arduino, it's called a "byte", so you can use it like that:
for (byte i = 0; i < currentpulse; i++) {....
It's far better than using the Arduino's "int" type (== int16_t) or "unsigned int" (== uint16_t) because the ATmega328 is 8-bit. So handling an 8-bit var is faster (a lot).
I hope it can help.