Hallo
Ich experimentiere schon eine Ganze zeit mit dem Bau eines Aquarien Computers rum, dieser ist soweit auch schon fertig , das Einzige was mir noch fehlt sind genaue Sensoren ,da die die ich zuerst verwendet habe sich gegenseitig stören , irgendwie logisch da PH strom erzeugt und der Leitwert strom ins Wasser leitet , allerdings hätte ich nicht gedacht das es bei ca 1m Abstand immer noch soviel ausmacht.
Also habe ich etwas das Internet durchsucht und in dann aufeine (zumindest auf den ersten Blick) recht einfache Lösung gefunden.
Die Amerikanische Firma Atlas-Scientific bietet "Chips" und Sensoren an die über I2C oder UART mehr oder weniger plug and play an einen Arduino oder Rasspberry pi angeschlossen werden könne und dann die werte auch recht gut wiedergeben . Das funktioniert auch alles soweit , ich habe dazu noch den Tentacle mini shield das heißt dann kein löten, sondern nur alles zusammenstecken , Sketch hochladen und über Seriellen Monitor ablesen.
Mein problem dabei ist jetzt das die Sensordaten nur char ausgeben und das ich für meine if abfragen z.b.
if (phWert < 7 )
{ mach dies und das}
ja einen float brauche
ich hab einige beispiele dafür im netz gefunden allerdings nicht wirklich etwas womit ich etwas anfangen kann bzw ich kann es nicht wirklich umsetzen. gibt es dafür irgendwo ein einfaches toutorial so das auch ein Laie das versteht ?
hier erstmal mein Sketch im Original vom hersteller
// WhiteBox Labs -- Tentacle Shield -- I2C example
// www.whiteboxes.ch
//
// How to retrieve continuous sensr readings from op to 8 Atlas Scientific devices on the I2C bus
// and send the readings to a host computer via serial.
//
// This code is intended to work on all 5V tolerant Arduinos. If using the Arduino Yun, connect
// to it's usb serial port. If you want to work with the Yun wirelessly, check out the respective
// Yun version of this example.
//
// USAGE:
//---------------------------------------------------------------------------------------------
// - Set all your EZO circuits to I2C before using this sketch.
// - You can use the "tentacle-steup.ino" sketch to do so)
// - Make sure each circuit has a unique I2C ID set
// - Adjust the variables below to resemble your setup: TOTAL_CIRCUITS, channel_ids, channel_names
// - Set host serial terminal to 9600 baud
//
//---------------------------------------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------------------------
#include <Wire.h> // enable I2C.
char sensordata[30]; // A 30 byte character array to hold incoming data from the sensors
byte sensor_bytes_received = 0; // We need to know how many characters bytes have been received
byte code = 0; // used to hold the I2C response code.
byte in_char = 0; // used as a 1 byte buffer to store in bound bytes from the I2C Circuit.
#define TOTAL_CIRCUITS 4 // <-- CHANGE THIS | set how many I2C circuits are attached to the Tentacle shield(s): 1-8
int channel_ids[] = {97, 98, 99, 100};// <-- CHANGE THIS.
// A list of I2C ids that you set your circuits to.
// This array should have 1-8 elements (1-8 circuits connected)
char *channel_names[] = {"DO", "ORP", "PH", "EC"}; // <-- CHANGE THIS.
// A list of channel names (must be the same order as in channel_ids[])
// it's used to give a name to each sensor ID. This array should have 1-8 elements (1-8 circuits connected).
// {"PH Tank 1", "PH Tank 2", "EC Tank 1", "EC Tank2"}, or {"PH"}
void setup() { // startup function
Serial.begin(9600); // Set the hardware serial port.
Wire.begin(); // enable I2C port.
}
void loop() {
for (int channel = 0; channel < TOTAL_CIRCUITS; channel++) { // loop through all the sensors
Wire.beginTransmission(channel_ids[channel]); // call the circuit by its ID number.
Wire.write('r'); // request a reading by sending 'r'
Wire.endTransmission(); // end the I2C data transmission.
delay(1000); // AS circuits need a 1 second before the reading is ready
sensor_bytes_received = 0; // reset data counter
memset(sensordata, 0, sizeof(sensordata)); // clear sensordata array;
Wire.requestFrom(channel_ids[channel], 48, 1); // call the circuit and request 48 bytes (this is more then we need).
code = Wire.read();
while (Wire.available()) { // are there bytes to receive?
in_char = Wire.read(); // receive a byte.
if (in_char == 0) { // null character indicates end of command
Wire.endTransmission(); // end the I2C data transmission.
break; // exit the while loop, we're done here
}
else {
sensordata[sensor_bytes_received] = in_char; // append this byte to the sensor data array.
sensor_bytes_received++;
}
}
Serial.print(channel_names[channel]); // print channel name
Serial.print(':');
switch (code) { // switch case based on what the response code is.
case 1: // decimal 1 means the command was successful.
Serial.println(sensordata); // print the actual reading
break; // exits the switch case.
case 2: // decimal 2 means the command has failed.
Serial.println("command failed"); // print the error
break; // exits the switch case.
case 254: // decimal 254 means the command has not yet been finished calculating.
Serial.println("circuit not ready"); // print the error
break; // exits the switch case.
case 255: // decimal 255 means there is no further data to send.
Serial.println("no data"); // print the error
break; // exits the switch case.
}
} // for loop
}
und hier der schon von mir "Umgebastelte" um die auslese werte zu trennen, also erstmal eine funktion für PH und eine Für EC , später soll noch Sauerstoff usw dazukommen
//
//---------------------------------------------------------------------------------------------
#include <Wire.h> // enable I2C.
char sensordata[30];
char sensordata2[30];// A 30 byte character array to hold incoming data from the sensors
byte sensor_bytes_received = 0;
byte sensor_bytes_received2 = 0;// We need to know how many characters bytes have been received
byte code = 0;
byte code2 = 0; // used to hold the I2C response code.
byte in_char = 0;
byte in_char2 = 0; // used as a 1 byte buffer to store in bound bytes from the I2C Circuit.
#define TOTAL_CIRCUITS 1
#define CIRCUITS2 1 // <-- CHANGE THIS | set how many I2C circuits are attached to the Tentacle shield(s): 1-8
int channel_ids[] = { 99};// <-- CHANGE THIS.
int channel_ids2[] = { 100};
// A list of I2C ids that you set your circuits to.
// This array should have 1-8 elements (1-8 circuits connected)
char *channel_names[] = { "PH"};
char *channel_names2[] = { "EC"};// <-- CHANGE THIS.
// A list of channel names (must be the same order as in channel_ids[])
// it's used to give a name to each sensor ID. This array should have 1-8 elements (1-8 circuits connected).
// {"PH Tank 1", "PH Tank 2", "EC Tank 1", "EC Tank2"}, or {"PH"}
float ecWert;
float phWert;
void pH(){
for (int channel = 0; channel < TOTAL_CIRCUITS; channel++) { // loop through all the sensors
Wire.beginTransmission(channel_ids[channel]); // call the circuit by its ID number.
Wire.write('r'); // request a reading by sending 'r'
Wire.endTransmission(); // end the I2C data transmission.
delay(1000); // AS circuits need a 1 second before the reading is ready
sensor_bytes_received = 0; // reset data counter
memset(sensordata, 0, sizeof(sensordata)); // clear sensordata array;
channel = phWert;
Wire.requestFrom(channel_ids[channel], 48, 1); // call the circuit and request 48 bytes (this is more then we need).
code = Wire.read();
while (Wire.available()) { // are there bytes to receive?
in_char = Wire.read(); // receive a byte.
if (in_char == 0) { // null character indicates end of command
Wire.endTransmission(); // end the I2C data transmission.
break; // exit the while loop, we're done here
}
else {
sensordata[sensor_bytes_received] = in_char; // append this byte to the sensor data array.
sensor_bytes_received++;
}
}
Serial.print(channel_names[channel]); // print channel name
Serial.print(':');
switch (code) { // switch case based on what the response code is.
case 1: // decimal 1 means the command was successful.
Serial.println(sensordata); // print the actual reading
break; // exits the switch case.
case 2: // decimal 2 means the command has failed.
Serial.println("command failed"); // print the error
break; // exits the switch case.
case 254: // decimal 254 means the command has not yet been finished calculating.
Serial.println("circuit not ready"); // print the error
break; // exits the switch case.
case 255: // decimal 255 means there is no further data to send.
Serial.println("no data"); // print the error
break; // exits the switch case.
}
} } // for loop
void EC(){
for (int channel2 = 0; channel2 < CIRCUITS2; channel2++) { // loop through all the sensors
Wire.beginTransmission(channel_ids2[channel2]); // call the circuit by its ID number.
Wire.write('r'); // request a reading by sending 'r'
Wire.endTransmission(); // end the I2C data transmission.
delay(1000); // AS circuits need a 1 second before the reading is ready
sensor_bytes_received2 = 0; // reset data counter
memset(sensordata2, 0, sizeof(sensordata2)); // clear sensordata array;
channel2 = ecWert ;
Wire.requestFrom(channel_ids2[channel2], 48, 1); // call the circuit and request 48 bytes (this is more then we need).
code2 = Wire.read();
while (Wire.available()) { // are there bytes to receive?
in_char2 = Wire.read(); // receive a byte.
if (in_char2 == 0) { // null character indicates end of command
Wire.endTransmission(); // end the I2C data transmission.
break; // exit the while loop, we're done here
}
else {
sensordata2[sensor_bytes_received2] = in_char2; // append this byte to the sensor data array.
sensor_bytes_received2++;
}
}
Serial.print(channel_names2[channel2]); // print channel name
Serial.print(':');
switch (code2) { // switch case based on what the response code is.
case 1: // decimal 1 means the command was successful.
Serial.println(sensordata2 ); // print the actual reading
break; // exits the switch case.
case 2: // decimal 2 means the command has failed.
Serial.println("command failed"); // print the error
break; // exits the switch case.
case 254: // decimal 254 means the command has not yet been finished calculating.
Serial.println("circuit not ready"); // print the error
break; // exits the switch case.
case 255: // decimal 255 means there is no further data to send.
Serial.println("no data"); // print the error
break; // exits the switch case.
}
} } // for loop
void setup() { // startup function
Serial.begin(9600); // Set the hardware serial port.
Wire.begin(); // enable I2C port.
}
void loop() {
pH();
EC();
Serial.print(ecWert);
}
Ja soweit war ich schon, nur finde ich irgendwie keine (für mich ) verständliche Anleitung wie ich das wo einfüge usw. immer nur Bruchstücke aus denen ich irgendwie nicht so richtig schlau werde. aber Trotzdem danke für den hinweiß,da ich jetzt weiß das ich auf dem richtigem weg bin mit meiner suche
Danke für die Tips allerdings komme ich immer noch nicht wirklich weiter
wo und wie muss ich denn da was ändern in den beispielen? und wie bzw an welcher stelle muss ich was dann einfügen ? Ich stehe irgendwie voll auf dem schlauch. :o
DemoSketch:
// How to retrieve continuous sensr readings from op to 8 Atlas Scientific devices on the I2C bus
// and send the readings to a host computer via serial.
Eine Text-Weiterleitungsdemo also.
Da wir deine Sensoren nicht haben und du die übertragenen Texte nicht zeigst, ist natürlich schwer, konkret zu helfen, denn: nicht jeder Text lässt sich sinnvoll in eine float - Zahl wandeln.
Da wir deine Sensoren nicht haben und du die übertragenen Texte nicht zeigst, ist natürlich schwer, konkret zu helfen, denn: nicht jeder Text lässt sich sinnvoll in eine float - Zahl wandeln.
Die Ausgabe zeigt
PH:7.521
EC:444.12
PH:7.521
EC:444.12
PH:7.521
EC:444.12
usw
eben je nach werten die gemessen wurden
und was ich brauche sind die Zahlen . Das würde ich ja noch hinbekommen indem ich PH oder EC aus dem sketch rauslösche allerdings kann ich dann damit immer noch nicht rechnen oder if abfragen machen
case 1: // decimal 1 means the command was successful.
float sensorvalue = atof(sensordata);
Serial.println(sensorvalue,3); // print the actual reading as a float number with 3 decimal digits
break; // exits the switch case.
Das würde ich ja noch hinbekommen indem ich PH oder EC aus dem sketch rauslösche allerdings kann ich dann damit immer noch nicht rechnen oder if abfragen mache
Völlig unnötig. Dafür gibt es Zeiger-Arithmetik
char str[] = "PH:7.521";
float value = atof(str + 3);
Eine Array Variable entspricht einem Zeiger auf das erste Element. Wenn du als 3 dazu addierst hast du Index 3 (das 4. Zeichen).
case 1: // decimal 1 means the command was successful.
float sensorvalue = atof(sensordata);
Serial.println(sensorvalue,3); // print the actual reading as a float number with 3 decimal digits
break; // exits the switch case.
?
Das Problem war das ich viel zu kompliziert gedacht habe
Ich war schon dabei die beispiele auseinander zunehmen und variablen dazu abzuändern und Programmblöcke + void Funktionen zu erstellen . dieses einfache beispiel hat das Problem allerdings genauso gelöst wie ich es wollte
vielen dank