char in if-Schelife

Hallo zusammen!

Ich habe dieses Wochenende meinen O2-Sensor über eine I2C-Verbindung an meinem Arduino getestet. Das hat auch wunderbar geklappt. Nun möchte ich den Sensorwert nutzen um über eine if-Abfrage, ein Relais zu steuern. Da der Wert ein char ist, bekomme ich aber in der if-Schleife eine Fehlermeldung. Ist es möglich den char-Wert (Sensorwert) in ein double oder so umzuwandeln?

Besten Dank und Grüsse!

Manu

Sketch für den O2-Sensor von Atlas scientific:

#include <Wire.h>                //enable I2C.
#include <ctype.h>               //for test numeric.
int address;                     //reserved for I2C ID number.
char computerdata[20];           //we make a 20 byte character array to hold incoming data from a pc/mac/other.
byte code = 0;                   //used to hold the I2C response code.
char sensor_data[20];            //we make a 20 byte character array to hold incoming data from the pH circuit.
byte in_char = 0;                //used as a 1 byte buffer to store in bound bytes from the pH Circuit.
byte i = 0;                      //counter used for sensor_data array.
int time = 1400;                 //used to change the delay needed depending on the command sent to the EZO Class pH Circuit.
byte DO_alarm;

void setup()                    //hardware initialization.
{
  Serial.begin(9600);           //enable serial port.
  Wire.begin();                 //enable I2C port.
}

void loop() {
  
  // *********** Dissolved Oxygen *************
  address = 97;             //default I2C ID number for EZO Dissolved Oxygen Circuit.
  readAtlas();
  Serial.print("DOX = ");
  Serial.println(sensor_data);          //print the data.
  Serial.println(Wire.read());
        if (sensor_data >= 7.0) {                                //if the DO is greater than or equal to 6.0
        Serial.println("high");                       //print "high" this is demonstrating that the Arduino is evaluating the DO as a number and not as a string
      }
      if (sensor_data <= 5.99) {                               //if the DO is less than or equal to 5.99
        Serial.println("low");                        //print "low" this is demonstrating that the Arduino is evaluating the DO as a number and not as a string
      }
  
}
//------------------------------ readSensor I²C -----------------------------------------------------
void readSensor() {
  if (computerdata[0] == 'c' || computerdata[0] == 'r')time = 5000; //if a command has been sent to calibrate or take a reading we wait 1400ms so that the circuit has time to take the reading.
  else time = 300;                  //if any other command has been sent we wait only 300ms.

  Wire.beginTransmission(address);  //call the circuit by its ID number.
  Wire.write(computerdata);         //transmit the command that was sent through the serial port.
  Wire.endTransmission();           //end the I2C data transmission.

  delay(time);                      //wait the correct amount of time for the circuit to complete its instruction.

  //DO_alarm = sensor_data;

  Wire.requestFrom(address, 20, 1); //call the circuit and request 20 bytes (this may be more then we need).
  code = Wire.read();               //the first byte is the response code, we read this separately.
  while (Wire.available()) {        //are there bytes to receive.
    in_char = Wire.read();          //receive a byte.
    if (isdigit(in_char)) {         //no text wanted.
      if (i == 1) {                 //insert comma after the first digit.
        sensor_data[i] = 44;
        i += 1;                     //incr the counter for the array element.
      }

      sensor_data[i] = in_char;     //load this byte into our array.
      i += 1;                       //incr the counter for the array element.
    }
    if (in_char == 0) {             //if we see that we have been sent a null command.
      i = 0;                        //reset the counter i to 0.
      Wire.endTransmission();       //end the I2C data transmission.
      break;                        //exit the while loop.
    }
  }
  memset(computerdata, 0, sizeof(computerdata));  // empty string
}
//------------------------------ readAtlas --------------------------------------------------------
  void readAtlas() {
    computerdata[0] = 'r';
    readSensor();
    computerdata[0] = 's';        //into powersave
    computerdata[1] = 'l';
    computerdata[2] = 'e';
    computerdata[3] = 'e';
    computerdata[4] = 'p';
    readSensor();
  }

Fehlermeldung:

Test.ino: In function 'void loop()':
Test:26: error: invalid operands of types 'char [20]' and 'double' to binary 'operator>='
Test:29: error: invalid operands of types 'char [20]' and 'double' to binary 'operator<='
invalid operands of types 'char [20]' and 'double' to binary 'operator>='

schau einmal hier:String zu long int: atol

Dann sieh dir dies an:

Da gibt es ein Beispiel zu deinem Char-Vergleich.

Vielen Dank für die schnelle Hilfestellung!

Ich hatte das gestern auch schon ausprobiert, dabei kommen bei mir aber komische Resultate raus und Fehlermeldungen habe ich auch keine erhalten. Habe ich da irgend was übersehen?

Vielen Dank und Grüsse
Manu

Code Ausschintt mit "atol":

#include <Wire.h>                //enable I2C.
#include <ctype.h>               //for test numeric.
int address;                     //reserved for I2C ID number.
char computerdata[20];           //we make a 20 byte character array to hold incoming data from a pc/mac/other.
byte code = 0;                   //used to hold the I2C response code.
char sensor_data[20];            //we make a 20 byte character array to hold incoming data from the pH circuit.
byte in_char = 0;                //used as a 1 byte buffer to store in bound bytes from the pH Circuit.
byte i = 0;                      //counter used for sensor_data array.
int time = 1400;                 //used to change the delay needed depending on the command sent to the EZO Class pH Circuit.
byte DO_alarm;
int number;                       //Test mit atol

void setup()                    //hardware initialization.
{
  Serial.begin(9600);           //enable serial port.
  Wire.begin();                 //enable I2C port.
  number = atol(sensor_data);
}

void loop() {
  
  // *********** Dissolved Oxygen *************
  address = 97;             //default I2C ID number for EZO Dissolved Oxygen Circuit.
  readAtlas();
  Serial.print("DOX = ");
  Serial.println(sensor_data);          //print the data.
  Serial.print(number);
  Serial.println(Wire.read());
        if (Wire.read() >= 7.0) {                                //if the DO is greater than or equal to 6.0
        Serial.println("high");                       //print "high" this is demonstrating that the Arduino is evaluating the DO as a number and not as a string
      }
      if (Wire.read() <= 5.99) {                               //if the DO is less than or equal to 5.99
        Serial.println("low");                        //print "low" this is demonstrating that the Arduino is evaluating the DO as a number and not as a string
      }

warum machst du das im Setup?

Edit:
außerdem versuchst du einen long Wert in ein int zu packen

versuch es mal so:

#include <Wire.h>                //enable I2C.
#include <ctype.h>               //for test numeric.
int address;                     //reserved for I2C ID number.
char computerdata[20];           //we make a 20 byte character array to hold incoming data from a pc/mac/other.
byte code = 0;                   //used to hold the I2C response code.
char sensor_data[20];            //we make a 20 byte character array to hold incoming data from the pH circuit.
byte in_char = 0;                //used as a 1 byte buffer to store in bound bytes from the pH Circuit.
byte i = 0;                      //counter used for sensor_data array.
int time = 1400;                 //used to change the delay needed depending on the command sent to the EZO Class pH Circuit.
byte DO_alarm;
float number;
void setup()                    //hardware initialization.
{
  Serial.begin(9600);           //enable serial port.
  Wire.begin();                 //enable I2C port.
}

void loop() {
 
  // *********** Dissolved Oxygen *************
  address = 97;             //default I2C ID number for EZO Dissolved Oxygen Circuit.
  readAtlas();
  number = atof(sensor_data);
  Serial.print("DOX = ");
  Serial.println(sensor_data);          //print the data.
  Serial.println(Wire.read());
  Serial.print(number);
        if (number >= 7.0) {                                //if the DO is greater than or equal to 6.0
        Serial.println("high");                       //print "high" this is demonstrating that the Arduino is evaluating the DO as a number and not as a string
      }
      if (number <= 5.99) {                               //if the DO is less than or equal to 5.99
        Serial.println("low");                        //print "low" this is demonstrating that the Arduino is evaluating the DO as a number and not as a string
      }
 
}
//------------------------------ readSensor I²C -----------------------------------------------------
void readSensor() {
  if (computerdata[0] == 'c' || computerdata[0] == 'r')time = 5000; //if a command has been sent to calibrate or take a reading we wait 1400ms so that the circuit has time to take the reading.
  else time = 300;                  //if any other command has been sent we wait only 300ms.

  Wire.beginTransmission(address);  //call the circuit by its ID number.
  Wire.write(computerdata);         //transmit the command that was sent through the serial port.
  Wire.endTransmission();           //end the I2C data transmission.

  delay(time);                      //wait the correct amount of time for the circuit to complete its instruction.

  //DO_alarm = sensor_data;

  Wire.requestFrom(address, 20, 1); //call the circuit and request 20 bytes (this may be more then we need).
  code = Wire.read();               //the first byte is the response code, we read this separately.
  while (Wire.available()) {        //are there bytes to receive.
    in_char = Wire.read();          //receive a byte.
    if (isdigit(in_char)) {         //no text wanted.
      if (i == 1) {                 //insert comma after the first digit.
        sensor_data[i] = 44;
        i += 1;                     //incr the counter for the array element.
      }

      sensor_data[i] = in_char;     //load this byte into our array.
      i += 1;                       //incr the counter for the array element.
    }
    if (in_char == 0) {             //if we see that we have been sent a null command.
      i = 0;                        //reset the counter i to 0.
      Wire.endTransmission();       //end the I2C data transmission.
      break;                        //exit the while loop.
    }
  }
  memset(computerdata, 0, sizeof(computerdata));  // empty string
}
//------------------------------ readAtlas --------------------------------------------------------
  void readAtlas() {
    computerdata[0] = 'r';
    readSensor();
    computerdata[0] = 's';        //into powersave
    computerdata[1] = 'l';
    computerdata[2] = 'e';
    computerdata[3] = 'e';
    computerdata[4] = 'p';
    readSensor();
  }

Vielen Dank für den Tipp! Jetzt funktioniert es zwar, aber ich erhalte nur eine einstellige Zahl ohne Nachkommastellen. Somit ist es mir nur möglich den Grenzwert auf eine ganze Zahl zu setzen.

was gibt Serial.println(sensor_data); und was gibt Serial.print(number); auf dem seriellen Monitor aus?

Nachfolgend die Serial-Ausgaben:

sensor_data = 9,01
number = 9.00
high
sensor_data = 8,82
number = 8.00
high

Was mir auch noch aufgefallen ist, ab einem O2-Wert von über 10, printet es eine 1 und keine 10.

ich habe mal zwei kleine Testprogramme geschrieben, lad sie mal hoch und schau dir an was der Serielle Monitor ausgibt.

Sketch 1

char sensor_data[5] ;  
float number;

void setup() {
  Serial.begin(9600);
}

void loop() {
sensor_data[0] = '1';
sensor_data[1] = '2';
sensor_data[2] = '.'; //Punkt
sensor_data[3] = '3';

 number = atof(sensor_data);
 Serial.print("sensor_data ");Serial.print(sensor_data);  
 Serial.print("   number ");Serial.println(number);  
}

Sketch 2

char sensor_data[5] ;  
float number;

void setup() {
  Serial.begin(9600);
}

void loop() {
sensor_data[0] = '1';
sensor_data[1] = '2';
sensor_data[2] = ','; //komma
sensor_data[3] = '3';

 number = atof(sensor_data);
 Serial.print("sensor_data ");Serial.print(sensor_data);  
 Serial.print("   number ");Serial.println(number);  
}

Bitte an den Null-Terminator denken!

Bitte an den Null-Terminator denken!

danke, geändert.

wenn du verstanden hast warum, dann versuch es so:

#include <Wire.h>                //enable I2C.
#include <ctype.h>               //for test numeric.
int address;                     //reserved for I2C ID number.
char computerdata[20];           //we make a 20 byte character array to hold incoming data from a pc/mac/other.
byte code = 0;                   //used to hold the I2C response code.
char sensor_data[20];            //we make a 20 byte character array to hold incoming data from the pH circuit.
byte in_char = 0;                //used as a 1 byte buffer to store in bound bytes from the pH Circuit.
byte i = 0;                      //counter used for sensor_data array.
int time = 1400;                 //used to change the delay needed depending on the command sent to the EZO Class pH Circuit.
byte DO_alarm;
float number;
void setup()                    //hardware initialization.
{
  Serial.begin(9600);           //enable serial port.
  Wire.begin();                 //enable I2C port.
}

void loop() {
 
  // *********** Dissolved Oxygen *************
  address = 97;             //default I2C ID number for EZO Dissolved Oxygen Circuit.
  readAtlas();
  number = atof(sensor_data);
  Serial.print("DOX = ");
  Serial.println(sensor_data);          //print the data.
  Serial.println(Wire.read());
  Serial.print(number);
        if (number >= 7.0) {                                //if the DO is greater than or equal to 6.0
        Serial.println("high");                       //print "high" this is demonstrating that the Arduino is evaluating the DO as a number and not as a string
      }
      if (number <= 5.99) {                               //if the DO is less than or equal to 5.99
        Serial.println("low");                        //print "low" this is demonstrating that the Arduino is evaluating the DO as a number and not as a string
      }
 
}
//------------------------------ readSensor I²C -----------------------------------------------------
void readSensor() {
  if (computerdata[0] == 'c' || computerdata[0] == 'r')time = 5000; //if a command has been sent to calibrate or take a reading we wait 1400ms so that the circuit has time to take the reading.
  else time = 300;                  //if any other command has been sent we wait only 300ms.

  Wire.beginTransmission(address);  //call the circuit by its ID number.
  Wire.write(computerdata);         //transmit the command that was sent through the serial port.
  Wire.endTransmission();           //end the I2C data transmission.

  delay(time);                      //wait the correct amount of time for the circuit to complete its instruction.

  //DO_alarm = sensor_data;

  Wire.requestFrom(address, 20, 1); //call the circuit and request 20 bytes (this may be more then we need).
  code = Wire.read();               //the first byte is the response code, we read this separately.
  while (Wire.available()) {        //are there bytes to receive.
    in_char = Wire.read();          //receive a byte.
    if (isdigit(in_char)) {         //no text wanted.
      if (i == 1) {                 //insert dot after the first digit.
        sensor_data[i] = 46;
        i += 1;                     //incr the counter for the array element.
      }

      sensor_data[i] = in_char;     //load this byte into our array.
      i += 1;                       //incr the counter for the array element.
    }
    if (in_char == 0) {             //if we see that we have been sent a null command.
      i = 0;                        //reset the counter i to 0.
      Wire.endTransmission();       //end the I2C data transmission.
      break;                        //exit the while loop.
    }
  }
  memset(computerdata, 0, sizeof(computerdata));  // empty string
}
//------------------------------ readAtlas --------------------------------------------------------
  void readAtlas() {
    computerdata[0] = 'r';
    readSensor();
    computerdata[0] = 's';        //into powersave
    computerdata[1] = 'l';
    computerdata[2] = 'e';
    computerdata[3] = 'e';
    computerdata[4] = 'p';
    readSensor();
  }

Vielen Dank für die Beispiele!

Ich habe mal nachgeforscht und gelesene, dass ein Komma dazu führt dass atof das als Ende der Zahl interpretiert und so keine Nachkommastellen generiert.

Was mir noch nicht klar ist, wiso werden Werte über 10 als 1,2,3 ect. ausgegeben?

da du hier

if (isdigit(in_char)) {         //no text wanted.
      if (i == 1) {                 //insert dot after the first digit.
        sensor_data[i] = 46;

nach der ersten Stelle ein Komma bzw. jetzt einen Punkt setzt