Problem med negativa floats i Arduino IDE

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
FormerMazda
Inlägg: 6066
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Problem med negativa floats i Arduino IDE

Inlägg av FormerMazda »

Blir svårformulerat i rubriken då det handlar om programmering av en ESP32 via Ardunio IDE.

Men jag håller på att utveckla mina rumsmojänger som ska mäta, visa och kommunicera.
Just nu har jag en ESP32 på bänken med en OLED via SPI, en DS18B20 via OneWire då, en TTL-RS485.
Programmet ser ut som prutt, men det är ju i nån testfas att få alla prylar att funka.

Funktionen är enkel, läs av tempgivaren, korrigera, presentera på OLED.
Temp och korrigering finns via modbus också.

Problemet nu är att så fort jag sätter korrigeringen till ett negativt tal så är det som en unsigned slår runt, men bara på OLED, aldrig via modbus.

Funkar på OLED och modbus:
Läst temp, oavsett positiv eller negativ temp.
Korrigering från 0 och positivt uppåt.

Funkar på modbus bara (OLED visar 65536 - vad som nu försöker visas)
Läst temp, oavsett positiv eller negativ temp.
Korrigering från -0,1 och neråt.

Jag förstår inte varför BÅDE temp och korrigering skiter sig när korrigering blir ett negativt värde. Tempen kan vara negativ eller positiv utan påverkan.
Och det slår ju om, men inga unsigned används ju.

Om jag i ModScan32 (modbus poller) väljer att läsa som "Decimal" (unsigned) istället för "Integer" (signed) så får jag samma värden som på OLED när OLED knasar.

Bifogar koden nedan, eftersom allt funkar över modbus så vill jag ju tro att det är konverteringen till sträng som skiter sig. Men bara när korrigering går negativt, inte temp.

Kod: Markera allt

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ModbusRTU.h>
#include <OneWire.h>
#include <DallasTemperature.h>

const int oneWireBus = 1; 
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);

#define REGN 10
#define SLAVE_ID 1
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
ModbusRTU mb;



void setup() {
  Serial2.begin(9600, SERIAL_8N1, 16, 17);
  mb.begin(&Serial2);
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
  display.display();
  delay(500); // Pause for 20 milliseconds
  display.clearDisplay();
  mb.slave(SLAVE_ID);
  mb.addHreg(REGN);
  mb.addHreg(11);
  
sensors.begin();
 
  
}

void loop() {
  sensors.requestTemperatures(); 
  float temperatureC = sensors.getTempCByIndex(0);
  int iCorr = mb.Hreg(11);
  float fCorr = (float)iCorr / 10.0;
  temperatureC = temperatureC + fCorr; //Korrigering
  int iTemp = temperatureC * 10; //Konvertera till int x10
  mb.Hreg(REGN, iTemp); //Sätt värde i holding 10 (REGN)
  
  //int iValue = mb.Hreg(REGN);
  String sTemp = String(temperatureC, 1); //konvertera till sträng med 1 decimal
  String sCorr = String(fCorr, 1); //konvertera till sträng med 1 decimal
  visa(sTemp, sCorr);
  mb.task();
  yield();  


 
  
}



//void visa(int iInValue) {
void visa(String sInValue, String sCorr) {
  display.clearDisplay();
  display.setTextSize(3);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(sInValue);
display.setCursor(0,24);             // rad 2
  display.println(sCorr);
  display.display();
}
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45175
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Problem med negativa floats i Arduino IDE

Inlägg av TomasL »

Funktionen String(.....) kan troligen inte hantera flyttal eller liknande
FormerMazda
Inlägg: 6066
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Problem med negativa floats i Arduino IDE

Inlägg av FormerMazda »

Den kan ju det för tempvisningen, både negativt och positivt värde.
Men för sCorr funkar den bara på positiva värden.
Men ja, det borde vara där det skiter sig.
Får nog stoppa in en massa serialprint här och där för debugging.
Mr Andersson
Inlägg: 1394
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Problem med negativa floats i Arduino IDE

Inlägg av Mr Andersson »

int iCorr = mb.Hreg(11);
Modbus::Hreg() är troligen uint16_t.

Du kan konvertera till signed med t.ex.

Kod: Markera allt

uint16_t uCorr = mb.Hreg(11);
int16_t iCorr = *(int16_t*)&uCorr;
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45175
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Problem med negativa floats i Arduino IDE

Inlägg av TomasL »

Gör en debug-utskrift på innehållet i fCorr och sCorr
Förresten varför använder du flyttal, varför inte heltal i stället?
Användarvisningsbild
pi314
Inlägg: 5680
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Problem med negativa floats i Arduino IDE

Inlägg av pi314 »

Jag hittar ingen dokumentation av funktionen String(). Den verkar behändig om den fungerar som du vill. Har du en länk till hur den ska användas?

Jag gjorde nyligen ungefär det du vill göra, med AHT10, DS18B20 och oled-display (med Adafruit_SSD1306.h).

Så här skrev jag då temperaturen på oled-displayen.

Kod: Markera allt

      display.print(tmpave,1); // Temperatur med en decimal
      display.print("\xF8"); // Gradtecken
      display.println("C");
När jag skulle göra motsvarande på en LCD-display (med LiquidCrystal_I2C.h) fanns inte lika bra funktioner för att formatera utskrifter på displayen. Då sparade jag temperaturen som heltal, 10 gånger mätvärdet och kodade så här för att visa temperaturen på LCD-displayen.

Kod: Markera allt

  tempi = (int) 10.0 * (tmpave+0.05); // heltal 10 x temperaturen
  sprintf(myresult1, "%04d", tempi); // Konvertera heltalet till sträng
  memcpy(s1, &myresult1[0], 3); // Plocka fram hela grader
  memcpy(&s1[3], &nullbyte, 1);
  memcpy(s2, &myresult1[3], 1); // Plocka fram decimalen
  lcd.print(s1); // Skriv heltalsdelen
  lcd.print('.'); // Skriv decimalpunkt
  lcd.print(s2); // Skriv decimalen
  lcd.printByte(7); // Degree, gradecken (egendefinierat)
  lcd.print("C ");
Klart krångligare och inte lika "vackert".
Kanske finns det enklare och snyggare sätt?

/Pi

Edit: I andra fallet ovan ligger temperaturen mellan 10 och 99°C. Med andra värden får man koda lite annorlunda.
hummel
Inlägg: 2259
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: Problem med negativa floats i Arduino IDE

Inlägg av hummel »

Användarvisningsbild
pi314
Inlägg: 5680
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Problem med negativa floats i Arduino IDE

Inlägg av pi314 »

Tack hummel!

"Parameters
val: a variable to format as a String. Allowed data types: string, char, byte, int, long, unsigned int, unsigned long, float, double.
base: (optional) the base in which to format an integral value.
decimalPlaces: only if val is float or double. The desired decimal places.
"

Då borde det fungera för FormerMazda...

/Pi
Användarvisningsbild
pi314
Inlägg: 5680
Blev medlem: 23 oktober 2021, 19:22:37
Ort: Stockholm

Re: Problem med negativa floats i Arduino IDE

Inlägg av pi314 »

Kan det vara så här?

String sTemp
och
String sCorr

definieras inte innan dom används första gången. Om man senare försöker lagra något där som är längre än det som lagras första gången så blir det knas.

Om man definierar dessa innan, med en storlek som är tillräcklig för alla fall, så kanske det fungerar?

/Pi
FormerMazda
Inlägg: 6066
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Problem med negativa floats i Arduino IDE

Inlägg av FormerMazda »

Tackar för alla svar!

Testade nu att skicka in float direkt till display.println, och på OLED fick jag värde med två decimaler.
Så OLED kan presentera float direkt, det är ju bra.
Så det testar ju också vad pi314 föreslog att testa, genom att inte använda dom stringarna alls.

Men felet kvarstår. :)

Nu lutar det mer åt att det är problem med signed/unsigned. Det blir ju rätt när jag läser modbusvärdena i ModScan, men ModScan kanske tar egna beslut och gör om unsigned till signed?
Ska forska i <ModbusRTU.h> och se om det finns nåt skrivet om saken.

Tomas: flyttal för vi lever i 2022 nu, samt att funktionen som läser av DS18B20 ger svar i flyttal. Men ja, man avråds ju från att använda det och jag skulle kunna göra om det till ett heltal och jobba med heltal ända till visningen genom att då hacka upp värdet i flera strängar/tecken.
Men det känns så .. uråldrigt. Den här ska ju inte göra så mycket mer än detta, så om det får jobba lite hårdare med flyttal spelar ingen roll så sett. Men om det inte funkar alls så spelar det större roll förstås.

Så Mr Andersson är på samma spår som mig nu. Ska testa förslaget.
FormerMazda
Inlägg: 6066
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Problem med negativa floats i Arduino IDE

Inlägg av FormerMazda »

Gick ju fort att testa, Mr Andersson har vunnit en klapp på egen axel! :D

Kod: Markera allt

uint16_t uCorr = mb.Hreg(11);
int16_t iCorr = *(int16_t*)&uCorr;
Med detta kan man ganska säkert anta att mb.Hreg svarar uint, konverteringen till int med ovan kod löste det, nu visar OLED samma som jag ser via modbus. (om än att modbus är x10 heltal då)

Och nu ser jag ju att OLED kan visa flyttal direkt, slapp jag konverteringen till sträng där!

Stort tack för all hjälp! :D
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45175
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Problem med negativa floats i Arduino IDE

Inlägg av TomasL »

Men varför går du vägen via flyttal, fullständigt onödigt, tar bara onödig tid och onödig plats.
FormerMazda
Inlägg: 6066
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Problem med negativa floats i Arduino IDE

Inlägg av FormerMazda »

Vet inte om du missade mitt svar?
Tomas: flyttal för vi lever i 2022 nu, samt att funktionen som läser av DS18B20 ger svar i flyttal. Men ja, man avråds ju från att använda det och jag skulle kunna göra om det till ett heltal och jobba med heltal ända till visningen genom att då hacka upp värdet i flera strängar/tecken.
Men det känns så .. uråldrigt. Den här ska ju inte göra så mycket mer än detta, så om det får jobba lite hårdare med flyttal spelar ingen roll så sett. Men om det inte funkar alls så spelar det större roll förstås.
Som sagt, funktionen sensors.getTempCByIndex ger ett flyttal.

Så där har jag ett oavsett. Och i slutänden vill jag ha minst en decimal.
Så annars behöver jag konvertera till heltal, för att sen hacka upp till decimal igen.
Visst, nu behöver jag ju göra till heltal för modbusen, men hellre det än att hacka en sträng för att få till decimalen igen.

Så fullständigt onödigt är det ju inte, tid och plats finns det i drivor.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45175
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Problem med negativa floats i Arduino IDE

Inlägg av TomasL »

Som jag fattade det så får du temperaturvärdet via modbus, och du skrev:
om än att modbus är x10 heltal då
FormerMazda
Inlägg: 6066
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Problem med negativa floats i Arduino IDE

Inlägg av FormerMazda »

Då förstår jag, näe tempvärdet kommer från annan funktion, i flyttal, men skrivs också till modbus och OLED.
Korrigeringen kommer från modbus däremot, och används till att räkna om ovan flyttal innan det skickas och visas.
Skriv svar