Hallo,
Bin neu hier im Forum.
Deshalb erstmal ein HALLO! an alle!
Habe mir einen TFMini Plus besorgt, da ich mit dem JSN-SR04T und dem HC-SR04 unzufrieden bin.
Bei dem einen ist die Streuung zu groß und der andere mißt nur richtig wenn es wärmer ist.
Für den TFMini benutze ich eine NodeMCU8266 von Amica.
Angeschlossen an 5V und Ground und D1 und D2.
Diese ist mit Arduino 1.8.12 geflasht.
Dafür habe ich mir über
link einen Code mit angepasster TFMini.cpp herunter geladen.
Das funktioniert auch sehr gut im Seriell Monitor.
Um aber das Ganze dann an MQTT zu senden habe ich den Code von
link ausprobiert.
Funktioniert auch, außer das ich keinen Wert in MQTT bekomme.
Also habe ich jetzt versucht beide Arduino-Codes zu kombinieren.
Jetzt nach ca. eineinhalb Wochen weiß ich aber nicht weiter.
Muss auch zugeben, dass ich keine Ahnung von Arduino habe!
Der Code funktioniert jetzt so, dass ich mal einen Wert in MQTT bekomme.
Dann mal nach einer Stunde oder zwei. Und dann auch wiederum nur einen am Tag.
Mein Arduino-Code:
Code:
/* This example shows how to use the TFMini module.
The nodeMCU have an build in Watchdog and therefore it is necessary,
that you delete/disable all <<Serial.print>> commands from the TFMini.cpp.
Otherwise you will run into an restart loop, because the Watchdog become
activated...
Wiring:
TFMini -> nodeMCU
SDA -> D2 -> 4 -> Tx
SCL -> D1 -> 5 -> Rx
VCC -> 5V
GND -> GND
*/
#include <Arduino.h>
#include <SoftwareSerial.h>
#include "TFMini.h"
#include <ESP8266WiFi.h>
#include "config.h"
//#include <ArduinoOTA.h>
#include <PubSubClient.h>
//#include "helper.h"
// Setup software serial port
SoftwareSerial mySerial(4, 5); // connection to TFMini
TFMini tfmini; // tfmini access
unsigned long previousMillis = 0; // access time
const long interval = 20000; // interval at which to measure (milliseconds)
WiFiClient wiFiClient;
PubSubClient client(wiFiClient);
byte clientStatus, prevClientStatus = 99;
/*
-----------------S E T U P-----------------
*/
void setup() {
// Step 1: Initialize hardware serial port (serial debug port)
Serial.begin(115200);
// wait for serial port to connect. Needed for native USB port only
while (!Serial);
// Step 2: Initialize the data rate for the SoftwareSerial port
mySerial.begin(TFMINI_BAUDRATE); // default boudrate is 115200
delay(10);
// Step 3: Initialize the TF Mini sensor
tfmini.begin(&mySerial);
Serial.println ("Initializing Serial and mySerial finished");
/* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
would try to act as both a client and an access-point and could cause
network-issues with your other WiFi-devices on your WiFi-network. */
// Set WIFI module to STA mode
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
// Wait
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// setupOTA();
// MQTT
client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);
digitalWrite(TRIGGER_PIN, LOW);
delay(2);
}
void ensureMQTTConnection (){
if (!client.connected()) {
Serial.println("Attempting MQTT connection...");
// Attempt to connect
if (MQTT_SERVER_USER_ID != "" && MQTT_SERVER_PASS != ""){
client.connect(MQTT_CLIENT_NAME, MQTT_SERVER_USER_ID, MQTT_SERVER_PASS);
}
else (client.connect(MQTT_CLIENT_NAME));
if(client.connected()){
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
/*
void setupOTA(){
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_SPIFFS
type = "filesystem";
}
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
}
*/
/*
-----------------L O O P-----------------
*/
void loop() {
// we will not use an delay...
// but we wait some short time before taking the next measurement
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last measure time
previousMillis = currentMillis;
// Take one TF Mini distance measurement
uint16_t dist = tfmini.getDistance();
uint16_t strength = tfmini.getRecentSignalStrength();
// Display the measurement
Serial.print(dist);
Serial.print(" cm Signal: ");
Serial.println(strength);
//MQWW Connectionint
ensureMQTTConnection();
static unsigned long last = millis();
if (millis() - last >= IDLE_TIME *1000) {
last = millis();
int waterlevel = tfmini.getDistance();
char cdist[16];
itoa(waterlevel ,cdist, 10);
client.publish(MQTT_TOPIC_NAME_LEVEL_CM, cdist);
}
client.loop();
//ArduinoOTA.handle();
delay(1000);
}
}
Die TFMini.cpp
Code:
/*
Arduino driver for Benewake TFMini time-of-flight distance sensor.
by Peter Jansen (December 11/2017)
This code is open source software in the public domain.
THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The names of the contributors may not be used to endorse or promote products
derived from this software without specific prior written permission.
*/
#include "TFMini.h"
// Constructor
TFMini::TFMini() {
// Empty constructor
}
boolean TFMini::begin(Stream* _streamPtr) {
// Store reference to stream/serial object
streamPtr = _streamPtr;
// Clear state
distance = -1;
strength = -1;
state = READY;
// Set standard output mode
setStandardOutputMode();
return true;
}
// Public: The main function to measure distance.
uint16_t TFMini::getDistance() {
int numMeasurementAttempts = 0;
while (takeMeasurement() != 0) {
numMeasurementAttempts += 1;
if (numMeasurementAttempts > TFMINI_MAX_MEASUREMENT_ATTEMPTS) {
// Serial.println ("TF Mini error: too many measurement attempts");
// Serial.println ("Last error:");
if (state == ERROR_SERIAL_NOHEADER) //Serial.println("ERROR_SERIAL_NOHEADER");
if (state == ERROR_SERIAL_BADCHECKSUM) //Serial.println("ERROR_SERIAL_BADCHECKSUM");
if (state == ERROR_SERIAL_TOOMANYTRIES) //Serial.println("ERROR_SERIAL_TOOMANYTRIES");
state = ERROR_SERIAL_TOOMANYTRIES;
distance = -1;
strength = -1;
return -1;
}
}
if (state == MEASUREMENT_OK) {
return distance;
} else {
return -1;
}
}
// Public: Return the most recent signal strength measuremenet from the TF Mini
uint16_t TFMini::getRecentSignalStrength() {
return strength;
}
// Private: Set the TF Mini into the correct measurement mode
void TFMini::setStandardOutputMode() {
// Set to "standard" output mode (this is found in the debug documents)
streamPtr->write((uint8_t)0x42);
streamPtr->write((uint8_t)0x57);
streamPtr->write((uint8_t)0x02);
streamPtr->write((uint8_t)0x00);
streamPtr->write((uint8_t)0x00);
streamPtr->write((uint8_t)0x00);
streamPtr->write((uint8_t)0x01);
streamPtr->write((uint8_t)0x06);
delay(100);
}
// Private: Handles the low-level bits of communicating with the TFMini, and detecting some communication errors.
int TFMini::takeMeasurement() {
int numCharsRead = 0;
uint8_t lastChar = 0x00;
// Step 1: Read the serial stream until we see the beginning of the TF Mini header, or we timeout reading too many characters.
while (1) {
if (streamPtr->available()) {
uint8_t curChar = streamPtr->read();
if ((lastChar == 0x59) && (curChar == 0x59)) {
// Break to begin frame
break;
} else {
// We have not seen two 0x59's in a row -- store the current character and continue reading.
lastChar = curChar;
numCharsRead += 1;
}
}
// Error detection: If we read more than X characters without finding a frame header, then it's likely there is an issue with
// the Serial connection, and we should timeout and throw an error.
if (numCharsRead > TFMINI_MAXBYTESBEFOREHEADER) {
state = ERROR_SERIAL_NOHEADER;
distance = -1;
strength = -1;
if (TFMINI_DEBUGMODE == 1)// Serial.println("ERROR: no header");
return -1;
}
}
// Step 2: Read one frame from the TFMini
uint8_t frame[TFMINI_FRAME_SIZE];
uint8_t checksum = 0x59 + 0x59;
for (int i=0; i<TFMINI_FRAME_SIZE; i++) {
// Read one character
while (!streamPtr->available()) {
// wait for a character to become available
}
frame[i] = streamPtr->read();
// Store running checksum
if (i < TFMINI_FRAME_SIZE-2) {
checksum += frame[i];
}
}
// Step 2A: Compare checksum
// Last byte in the frame is an 8-bit checksum
uint8_t checksumByte = frame[TFMINI_FRAME_SIZE-1];
if (checksum != checksumByte) {
state = ERROR_SERIAL_BADCHECKSUM;
distance = -1;
strength = -1;
if (TFMINI_DEBUGMODE == 1)// Serial.println("ERROR: bad checksum");
return -1;
}
// Step 3: Interpret frame
uint16_t dist = (frame[1] << 8) + frame[0];
uint16_t st = (frame[3] << 8) + frame[2];
uint8_t reserved = frame[4];
uint8_t originalSignalQuality = frame[5];
// Step 4: Store values
distance = dist;
strength = st;
state = MEASUREMENT_OK;
// Return success
return 0;
}
Die config.h
Code:
#define WIFI_SSID "xxxxxxxxxxxx" //enter SSID and pass without <>
#define WIFI_PASS "xxxxxxxxxxxxxxxx"
#define MQTT_SERVER_IP "192.168.1.141"
#define MQTT_SERVER_PORT 1886
#define MQTT_CLIENT_NAME "cistern-sensor"
#define MQTT_SERVER_USER_ID "admin" // leave quotes empty, if no authentication is required
#define MQTT_SERVER_PASS "xxxxxxxxxxxx"
//#define MQTT_TOPIC_NAME_LEVEL_PERCENT "cistern/level/percent"
//#define MQTT_TOPIC_NAME_LEVEL_LITERS "cistern/level/liters"
#define MQTT_TOPIC_NAME_LEVEL_CM "cistern/level/cm"
#define TRIGGER_PIN 5 //~D1
#define ECHO_PIN 4 //~D2
#define SENSOR_DISTANCE_TO_MAX_VOLUME 0 // in cm - minimum is 21
#define SENSOR_OFFSET 3 // use ruler and the mqtt topic cistern/level/cm to calibrate this value
#define IDLE_TIME 180 // in seconds
#define TIME_PERIOD_BETWEEN_READINGS 30 // in seconds
#define SAMPLE_SIZE 10
//#define CISTERN_HEIGHT 310 // in cm
//#define CISTERN_LENGTH 200 // in cm
/** ===============ADVANCED SETTINGS==================== **/
#define TRIGGER_PULSE_WIDTH 15 // in microseconds - adjust this setting if your sensor doesn't send the pulse
#define READING_TIMEOUT 60 // in milliseconds - max is 60ms - post-pulse time period after which the MCU gives up waiting for a return signal
Ich hoffe, dass mir jemand helfen kann.
Ich weiß nicht weiter!
Vergessen! Die Ausgabe vom Seriell Monitor:
Code:
14:15:55.683 ->
14:15:55.683 -> ets Jan 8 2013,rst cause:4, boot mode:(3,7)
14:15:55.683 ->
14:15:55.683 -> wdt reset
14:15:55.683 -> load 0x4010f000, len 1392, room 16
14:15:55.718 -> tail 0
14:15:55.718 -> chksum 0xd0
14:15:55.718 -> csum 0xd0
14:15:55.718 -> v3d128e5c
14:15:55.718 -> ~ld
14:15:55.891 -> Initializing Serial and mySerial finished
14:15:56.378 -> ..
14:15:56.899 -> WiFi connected
14:15:56.899 -> IP address:
14:15:56.899 -> 192.168.1.162
14:16:15.680 -> 5 cm Signal: 10624
14:16:15.680 -> Attempting MQTT connection...
14:16:15.715 -> connected
14:16:23.365 ->
14:16:23.365 -> ets Jan 8 2013,rst cause:4, boot mode:(3,7)
14:16:23.365 ->
14:16:23.365 -> wdt reset
14:16:23.365 -> load 0x4010f000, len 1392, room 16
14:16:23.400 -> tail 0
14:16:23.400 -> chksum 0xd0
14:16:23.400 -> csum 0xd0
14:16:23.400 -> v3d128e5c
14:16:23.400 -> ~ld
14:16:23.572 -> Initializing Serial and mySerial finished
14:16:24.058 -> ..
14:16:24.582 -> WiFi connected
14:16:24.582 -> IP address:
14:16:24.582 -> 192.168.1.162
14:16:31.849 ->
14:16:31.849 -> ets Jan 8 2013,rst cause:4, boot mode:(3,7)
14:16:31.849 ->
14:16:31.849 -> wdt reset
14:16:31.849 -> load 0x4010f000, len 1392, room 16
14:16:31.849 -> tail 0
14:16:31.884 -> chksum 0xd0
14:16:31.884 -> csum 0xd0
14:16:31.884 -> v3d128e5c
14:16:31.884 -> ~ld
14:16:32.056 -> Initializing Serial and mySerial finished
14:16:32.541 -> ..
14:16:33.061 -> WiFi connected
14:16:33.061 -> IP address:
14:16:33.061 -> 192.168.1.162
14:16:43.517 ->
14:16:43.517 -> ets Jan 8 2013,rst cause:4, boot mode:(3,7)
14:16:43.517 ->
14:16:43.517 -> wdt reset
14:16:43.552 -> load 0x4010f000, len 1392, room 16
14:16:43.552 -> tail 0
14:16:43.552 -> chksum 0xd0
14:16:43.552 -> csum 0xd0
14:16:43.552 -> v3d128e5c
14:16:43.552 -> ~ld
14:16:43.723 -> Initializing Serial and mySerial finished
14:16:44.243 -> ..
14:16:44.728 -> WiFi connected
14:16:44.728 -> IP address:
14:16:44.728 -> 192.168.1.162
14:17:03.539 -> 5 cm Signal: 10910
14:17:03.539 -> Attempting MQTT connection...
14:17:03.539 -> connected
Vielen Dank!
Habe es jetzt in kleinen Schritten aktualisiert.
Alles zusammen wollte der Editor oder Firefox nicht!?
Weiß nicht warum?????
Edit!
Die angepasste TFMini.cpp:
Code:
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The names of the contributors may not be used to endorse or promote products
derived from this software without specific prior written permission.
*/
#include "TFMini.h"
// Constructor
TFMini::TFMini() {
// Empty constructor
}
boolean TFMini::begin(Stream* _streamPtr) {
// Store reference to stream/serial object
streamPtr = _streamPtr;
// Clear state
distance = -1;
strength = -1;
state = READY;
// Set standard output mode
setStandardOutputMode();
return true;
}
// Public: The main function to measure distance.
uint16_t TFMini::getDistance() {
int numMeasurementAttempts = 0;
while (takeMeasurement() != 0) {
numMeasurementAttempts += 1;
if (numMeasurementAttempts > TFMINI_MAX_MEASUREMENT_ATTEMPTS) {
// Serial.println ("TF Mini error: too many measurement attempts");
// Serial.println ("Last error:");
if (state == ERROR_SERIAL_NOHEADER) //Serial.println("ERROR_SERIAL_NOHEADER");
if (state == ERROR_SERIAL_BADCHECKSUM) //Serial.println("ERROR_SERIAL_BADCHECKSUM");
if (state == ERROR_SERIAL_TOOMANYTRIES) //Serial.println("ERROR_SERIAL_TOOMANYTRIES");
state = ERROR_SERIAL_TOOMANYTRIES;
distance = -1;
strength = -1;
return -1;
}
}
if (state == MEASUREMENT_OK) {
return distance;
} else {
return -1;
}
}
// Public: Return the most recent signal strength measuremenet from the TF Mini
uint16_t TFMini::getRecentSignalStrength() {
return strength;
}
// Private: Set the TF Mini into the correct measurement mode
void TFMini::setStandardOutputMode() {
// Set to "standard" output mode (this is found in the debug documents)
streamPtr->write((uint8_t)0x42);
streamPtr->write((uint8_t)0x57);
streamPtr->write((uint8_t)0x02);
streamPtr->write((uint8_t)0x00);
streamPtr->write((uint8_t)0x00);
streamPtr->write((uint8_t)0x00);
streamPtr->write((uint8_t)0x01);
streamPtr->write((uint8_t)0x06);
delay(100);
}
// Private: Handles the low-level bits of communicating with the TFMini, and detecting some communication errors.
int TFMini::takeMeasurement() {
int numCharsRead = 0;
uint8_t lastChar = 0x00;
// Step 1: Read the serial stream until we see the beginning of the TF Mini header, or we timeout reading too many characters.
while (1) {
if (streamPtr->available()) {
uint8_t curChar = streamPtr->read();
if ((lastChar == 0x59) && (curChar == 0x59)) {
// Break to begin frame
break;
} else {
// We have not seen two 0x59's in a row -- store the current character and continue reading.
lastChar = curChar;
numCharsRead += 1;
}
}
// Error detection: If we read more than X characters without finding a frame header, then it's likely there is an issue with
// the Serial connection, and we should timeout and throw an error.
if (numCharsRead > TFMINI_MAXBYTESBEFOREHEADER) {
state = ERROR_SERIAL_NOHEADER;
distance = -1;
strength = -1;
if (TFMINI_DEBUGMODE == 1)// Serial.println("ERROR: no header");
return -1;
}
}
// Step 2: Read one frame from the TFMini
uint8_t frame[TFMINI_FRAME_SIZE];
uint8_t checksum = 0x59 + 0x59;
for (int i=0; i<TFMINI_FRAME_SIZE; i++) {
// Read one character
while (!streamPtr->available()) {
// wait for a character to become available
}
frame[i] = streamPtr->read();
// Store running checksum
if (i < TFMINI_FRAME_SIZE-2) {
checksum += frame[i];
}
}
// Step 2A: Compare checksum
// Last byte in the frame is an 8-bit checksum
uint8_t checksumByte = frame[TFMINI_FRAME_SIZE-1];
if (checksum != checksumByte) {
state = ERROR_SERIAL_BADCHECKSUM;
distance = -1;
strength = -1;
if (TFMINI_DEBUGMODE == 1)// Serial.println("ERROR: bad checksum");
return -1;
}
// Step 3: Interpret frame
uint16_t dist = (frame[1] << 8) + frame[0];
uint16_t st = (frame[3] << 8) + frame[2];
uint8_t reserved = frame[4];
uint8_t originalSignalQuality = frame[5];
// Step 4: Store values
distance = dist;
strength = st;
state = MEASUREMENT_OK;
// Return success
return 0;
}