Go Down

Topic: float to char/string probleem (Read 269 times) previous topic - next topic

jmnijsse

Nov 15, 2018, 09:46 am Last Edit: Nov 15, 2018, 10:45 am by jmnijsse
Hallo,

Ik probeer een Nextion display aan de gang te krijgen met temperatuur, pH en geleidbaarheidswaarden van een aquarium, en dat lukt vrij redelijk.

De temperatuur geeft ie prima weer.

Dus ik dacht op dezelfde manier de pH te doen, maar dat pikt ie niet.

Code: [Select]

void get_temp() {
  sensors.requestTemperatures();

  float t = sensors.getTempCByIndex(0);

  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {
    return;
  }
  // Update temperature in Celsius
  static char temperatureCTemp[6];
  dtostrf(t, 6, 1, temperatureCTemp);
  tTempC.setText(temperatureCTemp);
}


Dit is het stukje wat ik voor de temperatuur (een digitale DS18B20 sensor) gebruik. En dat wordt prima weergegeven.
In de laatste 3 regels wordt de float in een char-array gezet, waarna hij met setText naar het display gestuurd wordt.

Op eenzelfde manier dacht ik de pH te doen.

Code: [Select]
void get_pH()
{

  float sensorValue;
  //  int m;
  //  long sensorSum;
  int buf[10];                //buffer for read analog
  for (int i = 0; i < 10; i++) //Get 10 sample value from the sensor for smooth the value
  {
    buf[i] = analogRead(A0); //Connect the PH Sensor to A0 port
    delay(10);
  }
  for (int i = 0; i < 9; i++) //sort the analog from small to large
  {
    for (int j = i + 1; j < 10; j++)
    {
      if (buf[i] > buf[j])
      {
        int temp = buf[i];
        buf[i] = buf[j];
        buf[j] = temp;
      }
    }
  }
  avgValue = 0;

  for (int i = 2; i < 8; i++)               //take the average value of 6 center sample
    avgValue += buf[i];

  sensorValue = avgValue / 6;
  float pHfloat = (5.70 - 1000 * (sensorValue - 365) * Vref / 59.16 / 1023, 1);
  //  Serial.print("pH = ");
  //  Serial.println(pHfloat);
  static char pH[4];
  dtostrf(pHfloat, 4, 1, pH);
  tpH.setText(pH);
  delay(2000);

}


Waarin in de laatste 4 regels die float pHfloat naar een char-array wordt omgezet.

In de berekening van de pHfloat staat als laatste argument achter 1023 (,1) het aantal decimalen.
Op het display komt in dit geval 1.0 te staan.

Verander ik dat aantal decimalen in 2 komt er op het display 2.0 te staan. En bij 3, 3.0 enzovoorts.

Maar dus niet de pH, die ik zoek. En die in een extern programma, zonder die dtostrf-functie, wel goed wordt weergegeven.

  • Kan iemand mij duidelijk maken hoe zo'n float - string conversie precies werkt? Er wordt immers een functie gebruikt waarin ik ook iets van string zie staan. De relatie tussen die float, string, char is mij niet goed duidelijk. En de engelstalige info helpt mij niet genoeg om het echt door te hebben
  • Gaat er in die pH berekening iets fout, waardoor alleen die 1.0, 2.0 etc. worden getoond?
  • Heeft dit misschien ook nog te maken met het feit dat de temperatuur een digitaal signaal is en de pH meter een analoog signaal? LIjkt me niet, want bij beiden komt er een float getal uit?


Bij voorbaat dank alvast voor het meedenken.

Groet,
Johan

jmnijsse

#1
Nov 15, 2018, 12:30 pm Last Edit: Nov 15, 2018, 12:31 pm by jmnijsse
UPDATE:

Ik heb dat laatste getal (1, 2, etc, voor de decimalen) weggehaald en nu doet ie het wel!
Maar dat had ik, dacht ik, al eerder geprobeerd en toen zonder resultaat.
Mogelijk was er toen toch nog iets anders gewijzigd.

In die dtostrf functie zit ook een getal voor de decimalen. Zou dat geconflicteerd hebben?


jmnijsse

#2
Nov 15, 2018, 03:03 pm Last Edit: Nov 15, 2018, 03:06 pm by jmnijsse
Toch weer een toevoeging:

De analogRead-functie doet vervelend.
Ik wil de volgende waarde toevoegen en test die met een potmeter.
Die ik vervolgens op dezelfde manier in een ander veldje op het display wil weergeven.

Code: [Select]

void get_pot()
{
 
  float x = analogRead(A1);
  float y = x / 3.00;

  static char pot[6];
  dtostrf(y, 6, 2, pot);
  tPot.setText(pot);

}


Als ik deze code mee laat draaien, wordt er geen enkele waarde (dus geen temp, en pH) doorgegeven.
Verander ik die analogRead(A1) in bijv. simpel het getal 1000, geeft hij mooi 333.33 aan én komt bijv. de temperatuur weer tevoorschijn. Zet ik dan de pH erbij, verdwijnt de potmeter weer.
Ik snap er weinig meer van.

Voor de volledigheid hier heel de code:

Code: [Select]
/*
   Rui Santos
   Complete Project Details http://randomnerdtutorials.com
*/

//pH-Sensor
#define Vref 4.95
unsigned long int avgValue;     //Store the average value of the sensor feedback
int i = 0;

//Temperature Sensor
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

#include "Nextion.h"

NexText tTempC = NexText(0, 3, "t1");
NexText tpH = NexText(0, 6, "t4");
NexText tPot = NexText(0, 9, "t7");


void setup(void) {

  Serial.begin(9600);
  sensors.begin();
  // You might need to change NexConfig.h file in your ITEADLIB_Arduino_Nextion folder
  // Set the baudrate which is for debug and communicate with Nextion screen
  nexInit();

}

void loop(void)
{

  get_temp();
  get_pH();
  get_pot();

}

void get_temp()
{
 
  sensors.requestTemperatures();

  float t = sensors.getTempCByIndex(0);

  //convert to char
  static char temperatureCTemp[6];
  dtostrf(t, 6, 1, temperatureCTemp);

  //update display
  tTempC.setText(temperatureCTemp);

}

void get_pH()
{

  float sensorValue;
  int buf[10];                //buffer for read analog
  for (int i = 0; i < 10; i++) //Get 10 sample value from the sensor for smooth the value
  {
    buf[i] = analogRead(A0); //Connect the PH Sensor to A0 port
    delay(10);
  }
  for (int i = 0; i < 9; i++) //sort the analog from small to large
  {
    for (int j = i + 1; j < 10; j++)
    {
      if (buf[i] > buf[j])
      {
        int temp = buf[i];
        buf[i] = buf[j];
        buf[j] = temp;
      }
    }
  }
  avgValue = 0;

  for (int i = 2; i < 8; i++)               //take the average value of 6 center sample
    avgValue += buf[i];

  sensorValue = avgValue / 6;
  float pHfloat = (5.70 - 1000 * (sensorValue - 365) * Vref / 59.16 / 1023);

  //convert to char
  static char pH[4];
  dtostrf(pHfloat, 4, 1, pH);
 
  //update display
  tpH.setText(pH);
 
}

void get_pot()
{

  float x = analogRead(A1) / 3.00;

  //convert to char
  static char pot[6];
  dtostrf(x, 6, 2, pot);

  //update display
  tPot.setText(pot);

}




photoncatcher

Beste jmnijsse - ook ik heb hopeloos zitten knoeien met het probleem om twee floats ieder met een decimaal (temperatuur, bv 10,5 graden - en luchtvochtigheid, b.v. 50,3%) via seriele communicatie van de ene Arduino naar een andere te krijgen en met een aan die tweede Arduino gehangen lcd display te displayen.
Seriele communicatie tussen Arduino's vindt plaats met bytes dus je moet je float eerst naar bytes converteren. Ik heb dat opgelost door in Arduino #1 de gevonden waarde van bv temperatuur met 10 te vermenigvuldigen. Daarmee heb ik de decimaal in feite 1 plaatsje naar links verplaatst. Dan laat ik dstostrf erop los en ik verstuur de string. Op  Arduino nummer 2 komt de string binnen en hier laat ik  atof  erop los en ik deel daarna door 10. Bingo.

Het hele verhaal is te lezen op mijn Arduinohoekje:
http://www.zonnepanelen.wouterlood.com/arduino-bare-basics/4-arduino-communicating-data-from-multiple-sensors-to-a-neighbor-arduino-for-display/

succes, Photoncatcher

nicoverduin

#4
Nov 17, 2018, 11:50 am Last Edit: Nov 17, 2018, 11:51 am by nicoverduin
Dit is sowieso niet goed:
Code: [Select]
//convert to char
  static char temperatureCTemp[6];
  dtostrf(t, 6, 1, temperatureCTemp);

Je maakt een char array van 6 bytes. Vervolgens ga je die vullen met 6 tekens. ECHTER bij een char array moet er altijd nog een 0x00 staan om hem af te sluiten. Dat het in het verleden goed gaat is toeval. Je moet hem dus 7 bytes maken. Daarnaast is het maken van static niet nodig. Na het verzenden naar de Nextion is de string in de functie niet meer nodig.

En hier maak je dezelfde fout
Code: [Select]
//convert to char
  static char pH[4];
  dtostrf(pHfloat, 4, 1, pH);


Met vriendelijke groet / kindest regards
Nico Verduin
www.verelec.nl
Do not PM me for personal consultancy unless you are willing to pay for it.

jmnijsse

Bedankt beiden voor de reactie. Ik ga er weer mee aan de slag.

Is een static char eigenlijk te vergelijken met een const int bijvoorbeeld?

Wat die aantallen betreft:

Ik had gedacht er kunnen maximaal 5 getallen staan als temperatuur (al is dat voor een aquarium niet te hopen...  :smiley-confuse: )
Dus een char array van 6 voor die 0x00.
Maar ik ga deze tip eens proberen.

En @photoncatcher: ik ga je verhaal nog eens lezen. Al stuur ik niet door naar een andere arduino, er zullen vast parallellen inzitten.

Gr.
Johan

jmnijsse

Het lijkt te werken! Dank!
Code: [Select]

  char pH[4];
  dtostrf(pHfloat, 3, 1, pH);
 
  //update display
  tpH.setText(pH);

Go Up