Ich versuche gerade mit Wemos D1 Minis ein paar LED-Streifen (WS2812b) per WLAN zu steuern.
Mein Problem:
Wie überprüfe ich bei jeder Loop den Status von Wifi und SQL-Datenbank, ohne dass es ewig dauert?
Mein Versuch 1
void setup() {
[...]
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
MYSQL_DISPLAY0(".");
}
while (conn.connect(server, server_port, user, password) != RESULT_FAIL) {
delay(500);
MYSQL_DISPLAY0(".");
}
[...]
}
void loop() {
// der Code für die LEDs
}
--> Problem: Sobald die Wifi-Verbindung aus irgendeinem Grund kurz weg ist, stürzt der D1 Mini ab.
Daher brauche ich eine andere Lösung, aber meine einzige Idee ist so etwas. Damit bin ich auch nicht sonderlich glücklich, da glaube (!), dass diese Lösung durch die if-Schleife Probleme machen könnte.
Mein Versuch 2
void loop() {
while ((WiFi.status() == WL_CONNECTED) && (conn.connect(server, server_port, user, password))) {
{
// der Code für die LEDs
}
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
MYSQL_DISPLAY0(".");
}
while (conn.connect(server, server_port, user, password) != RESULT_FAIL) {
delay(500);
MYSQL_DISPLAY0(".");
}
}
---> Problem: Jede Loop dauert jetzt ca. 500ms, so dass die Rainbow-Effekte nicht mehr laufen.
Vermutlich werde ich es nie realisieren, aber ich habe stets live-Lichttechnik (Ersatz für DMX) im Hinterkopf, d.h. einen schnellen Lichtwechsel zur Musik.
Aber das ist bei diesem Projekt gerade nicht mein Problem sondern als primäres Problem der Absturz und als sekundäres das zurückgeben von Arrays bei einer Funktion.
Über die if-Schleife wird wifi.begin() ja nur aufgerufen, falls keine sql-Verbindung vorhanden ist, d.h. in dem Fall verbindet er sich mit dem WiFi erst mal neu und stellt dann eine db-Verbindung her, aber nicht standardmäßig in jeder Loop.
Ist das nicht gut?
Ich kann verstehen, dass das gerade sehr sinnvoll wäre, aber ich wüsste gerade nicht wie. Ich kann es nicht wirklich auf einen Code-Abschnitt einschränken und leider tritt es auch erst (bislang) nach mindestens 45 Minuten Laufzeit auf ^^ ich kann es nicht reproduzieren :-/
Hallo,
das halte ich für eine Ausrede, erstens ist das Internet voll mit Beispielen, zweitens könntest Du ein globales Array nehmen das umschiffst Du Dein "Problem".
Heinz
Da Du uns immer nur mit Häppchen abspeist, ist sinnvolle Hilfe unmöglich.
Welche Lib verwendest Du zum Zugriff auf MySQL (Link bitte).
Wie @noiasca bereits schrieb, ohne einen kompilierbaren Sketch wird das nur stochern im Nebel und das macht keiner gern.
Ausrede würde ich jetzt nicht sagen. Ich habe es nicht innerhalb von 15 Minuten verstanden und da es nicht mein Problem war, habe ich mich halt nicht weiter damit beschäftigt @Tommy56 hatte mit seinem Hinweis da jedoch natürlich vollständig recht und wenn ich dazu zufällig auch Tipps bekomme, dann nehme ich die gerne, aber mein ursprüngliches Problem war halt einfach ein anderes
Da hast du wohl recht.
Tut mir voll Leid ^^ ich versuche es mal so nachvollziehbar wie möglich zu machen
Folgender Fehler tritt im Abstand von 75 Minuten auf (und ich habe keine Ahnung welcher Teil des Programms ihn verursacht):
// #################################################################################################################
// #################################################################################################################
// ################################## DEFINES MARIADB ##############################################################
// #################################################################################################################
// #################################################################################################################
#include "defines.h"
#include "Credentials.h"
#include <MySQL_Generic.h>
#define USING_HOST_NAME false
#if USING_HOST_NAME
// Optional using hostname, and Ethernet built-in DNS lookup
char server[] = "server.local"; // change to your server's hostname/URL
#else
IPAddress server(192, 168, 100, 2);
#endif
uint16_t server_port = 3306; //3306;
char default_database[] = "home"; //"test_arduino";
char default_table[] = "lights"; //"test_arduino";
String default_column = "brightness";
String default_value = "41";
String queryBrightness = String("SELECT brightness FROM ") + default_database + "." + default_table
+ " WHERE device_id = '" + default_value + "'";
String queryPattern = String("SELECT pattern FROM ") + default_database + "." + default_table
+ " WHERE device_id = '" + default_value + "'";
String queryRed = String("SELECT red FROM ") + default_database + "." + default_table
+ " WHERE device_id = '" + default_value + "'";
String queryGreen = String("SELECT green FROM ") + default_database + "." + default_table
+ " WHERE device_id = '" + default_value + "'";
String queryBlue = String("SELECT blue FROM ") + default_database + "." + default_table
+ " WHERE device_id = '" + default_value + "'";
String queryDuration = String("SELECT duration FROM ") + default_database + "." + default_table
+ " WHERE device_id = '" + default_value + "'";
MySQL_Connection conn((Client *)&client);
// Create an instance of the cursor passing in the connection
MySQL_Query sql_query = MySQL_Query(&conn);
// #################################################################################################################
// #################################################################################################################
// ################################## DEFINES NEOPIXEL #############################################################
// #################################################################################################################
// #################################################################################################################
// A non-blocking everyday NeoPixel strip test program.
// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
// connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
// a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)
#include <Adafruit_NeoPixel.h>
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#ifdef ESP32
// Cannot use 6 as output for ESP. Pins 6-11 are connected to SPI flash. Use 16 instead.
#define LED_PIN 2
#else
#define LED_PIN 2
#endif
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 300
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
unsigned long pixelPrevious = 0; // Previous Pixel Millis
unsigned long patternPrevious = 0; // Previous Pattern Millis
int patternCurrent = 0; // Current Pattern Number
int patternInterval = 5000; // Pattern Interval (ms)
int pixelInterval = 50; // Pixel Interval (ms)
int pixelQueue = 0; // Pattern Pixel Queue
int pixelCycle = 0; // Pattern Pixel Cycle
uint16_t pixelCurrent = 0; // Pattern Current Pixel Number
uint16_t pixelNumber = LED_COUNT; // Total Number of Pixels
// #################################################################################################################
// #################################################################################################################
// ################################## VOID SETUP ###################################################################
// #################################################################################################################
// #################################################################################################################
#include "Database.h"
#include "Neopixel.h"
int brightness;
int brightness_old;
int brightness_change;
int pattern_old;
int pattern_change;
int red_old;
int blue_old;
int green_old;
int brightness_start = 20;
int red;
int green;
int blue;
int duration;
void setup()
{
Serial.begin(115200);
while (!Serial && millis() < 5000); // wait for serial port to connect
MYSQL_DISPLAY1("\nStarting Basic_Select_WiFi on", BOARD_NAME);
MYSQL_DISPLAY(MYSQL_MARIADB_GENERIC_VERSION);
// Begin WiFi section
MYSQL_DISPLAY1("Connecting to", ssid);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
MYSQL_DISPLAY0(".");
}
Serial.println("");
// print out info about the connection:
MYSQL_DISPLAY1("Connected to network. My IP address is:", WiFi.localIP());
MYSQL_DISPLAY3("Connecting to SQL Server @", server, ", Port =", server_port);
// MYSQL_DISPLAY5("User =", user, ", PW =", password, ", DB =", default_database);
// ######################## NEOPIXEL ##################################
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(brightness_start); // Set BRIGHTNESS to about 1/5 (max = 255)
MYSQL_DISPLAY0("Connecting to Database");
while (conn.connect(server, server_port, user, password) != RESULT_FAIL) {
delay(500);
MYSQL_DISPLAY0(".");
}
Serial.println("");
Serial.println("Setup completed.");
}
// #################################################################################################################
// #################################################################################################################
// ################################## VOID LOOP ####################################################################
// #################################################################################################################
// #################################################################################################################
void loop()
{
unsigned long anfang = millis();
int counter; // Loop counter for brightness changes
int n = 2; // Brightness +-1 every n'th Loop
if (conn.connected()) {
red = runQuery(queryRed);
green = runQuery(queryGreen);
blue = runQuery(queryBlue);
duration = runQuery(queryDuration);
brightness = runQuery(queryBrightness);
patternCurrent = runQuery(queryPattern);
}
else {
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
MYSQL_DISPLAY0(".");
}
while (conn.connect(server, server_port, user, password) != RESULT_FAIL) {
delay(500);
MYSQL_DISPLAY0(".");
}
}
// ######################## BRIGHTNESS ##########################
if (brightness_change != brightness) {
Serial.println("[CHANGE] Brightness set to " + String(brightness));
brightness_change = brightness;
}
if (brightness_old != brightness and brightness_old < 256) {
if (counter % n == 0) {
int differenz = abs(brightness - brightness_old);
if (brightness_old > brightness ) {
brightness_old--;
brightness_old--;
strip.setBrightness(brightness_old);
strip.show();
}
if (brightness_old < brightness and brightness_old <= 253) {
brightness_old++;
brightness_old++;
strip.setBrightness(brightness_old);
strip.show();
}
}
counter++;
} else {
counter = 0;
}
// ######################## PATTERN ##########################
if (pattern_change != patternCurrent) {
Serial.println("[CHANGE] Pattern set to " + String(patternCurrent));
pattern_change = patternCurrent;
}
unsigned long currentMillis = millis(); // Update current time
if ((currentMillis - patternPrevious) >= patternInterval) { // Check for expired time
patternPrevious = currentMillis;
// patternCurrent++; // Advance to next pattern
if (patternCurrent >= 10)
patternCurrent = 0;
}
int timer = millis() - anfang;
// ######################## SWITCH-CASE ##########################
// if (currentMillis - pixelPrevious >= pixelInterval) { // Check for expired time
pixelPrevious = currentMillis; // Run current frame
switch (patternCurrent) {
case 9:
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, strip.Color(red, green, blue)); // Set pixel's color (in RAM)
}
strip.show();
// colorWipe(strip.Color(red, green, blue), 50 - timer); // Individual Color
break;
case 8:
theaterChaseRainbow(50 - timer); // Rainbow-enhanced theaterChase variant
break;
case 7:
rainbow(duration - timer); // Flowing rainbow cycle along the whole strip
break;
case 6:
theaterChase(strip.Color(0, 0, 127), 50 - timer); // Blue
break;
case 5:
theaterChase(strip.Color(127, 0, 0), 50 - timer); // Red
break;
case 4:
theaterChase(strip.Color(127, 127, 127), 50 - timer); // White
break;
case 3:
colorWipe(strip.Color(0, 0, 255), 50); // Blue
break;
case 2:
colorWipe(strip.Color(0, 255, 0), 50 - timer); // Green
break;
case 1:
colorWipe(strip.Color(84, 0, 24), 50 - timer); // Red
break;
default:
colorWipe(strip.Color(255, 200, 25), 50 - timer); // Warmwhite
break;
}
// }
}
Credentials.h
#ifndef Credentials_h
#define Credentials_h
char ssid[] = "XXXXX"; // your network SSID (name)
char pass[] = "XXXXX"; // your network password
char user[] = "XXXXX"; // MySQL user login username
char password[] = "XXXXX"; // MySQL user login password
#endif //Credentials_h
Database.h
int runQuery(String query)
{
row_values *row = NULL;
long result = 0;
// Execute the query
sql_query.execute(query.c_str());
// Fetch the columns (required) but we don't use them.
sql_query.get_columns();
// Read the row (we are only expecting the one)
do
{
row = sql_query.get_next_row();
if (row != NULL)
{
result = atol(row->values[0]);
}
} while (row != NULL);
// Now we close the cursor to free any memory
sql_query.close();
return result;
}
Neopixel.h
void pulse() {
// fade in
for (int x = 80; x < 160; x++) {
strip.setBrightness(x);
}
// fade out
for (int x = 80; x >= 160; x--) {
strip.setBrightness(x);
}
}
// Some functions of our own for creating animated effects -----------------
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
if(pixelInterval != wait)
pixelInterval = wait; // Update delay time
strip.setPixelColor(pixelCurrent, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
pixelCurrent++; // Advance current pixel
if(pixelCurrent >= pixelNumber) // Loop the pattern from the first LED
pixelCurrent = 0;
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
if(pixelInterval != wait)
pixelInterval = wait; // Update delay time
for(int i = 0; i < pixelNumber; i++) {
strip.setPixelColor(i + pixelQueue, color); // Set pixel's color (in RAM)
}
strip.show(); // Update strip to match
for(int i=0; i < pixelNumber; i+=3) {
strip.setPixelColor(i + pixelQueue, strip.Color(0, 0, 0)); // Set pixel's color (in RAM)
}
pixelQueue++; // Advance current pixel
if(pixelQueue >= 3)
pixelQueue = 0; // Loop the pattern from the first LED
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(uint8_t wait) {
if(pixelInterval != wait)
pixelInterval = wait;
for(uint16_t i=0; i < pixelNumber; i++) {
strip.setPixelColor(i, Wheel((i + pixelCycle) & 255)); // Update delay time
}
strip.show(); // Update strip to match
pixelCycle++; // Advance current cycle
if(pixelCycle >= 256)
pixelCycle = 0; // Loop the cycle back to the begining
}
//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
if(pixelInterval != wait)
pixelInterval = wait; // Update delay time
for(int i=0; i < pixelNumber; i+=3) {
strip.setPixelColor(i + pixelQueue, Wheel((i + pixelCycle) % 255)); // Update delay time
}
strip.show();
for(int i=0; i < pixelNumber; i+=3) {
strip.setPixelColor(i + pixelQueue, strip.Color(0, 0, 0)); // Update delay time
}
pixelQueue++; // Advance current queue
pixelCycle++; // Advance current cycle
if(pixelQueue >= 3)
pixelQueue = 0; // Loop
if(pixelCycle >= 256)
pixelCycle = 0; // Loop
}
Dann orientiere Dich doch einfach an diesem Beispiel Deiner Lib. In Zeile 180 ist der Zugriff auf die einzelnen Felder einer Query mit mehreren Feldern gezeigt.
Irgendwie hängst Du vermutlich in einer Schleife fest wdt ist der "Wachund" ich weiß nicht genau worauf der beim ESP eingestellt ist. Jedenfalls wenn der lopp zu lange dauert kann das System nicht schnell genug mit dem WIFI werkeln. Wenn Du rausbekommst wo er festhängt könntest Du ein delay(0) da einbauen , aber der richtige Weg ist das nicht. Also bau noch ein paar Seriellprint("ich bin gerade hier" ) damit Du debuggen kannst.
Heinz