Portable Arduino IDE einrichten
Eine Aktion einmalig ausführen
Eine Aktion nur bei jedem x-ten Aufruf einer Funktion ausführen
Schalten über den Tageswechsel
Mehrere portable Esp Versionen nutzen
Lade die Arduino IDE als "Windows ZIP file for non admin install" herunter. Entpackt hast du aktuell den Ordner "arduino-1.8.19". Am besten gleich umbenennen in "Arduino_1.8.19_Master". Gehe jetzt in den Ordner und füge einen Ordner Namens "portable" hinzu. Anschließend die arduino.exe starten und gleich im Menü zu Datei/Voreinstellungen gehen. Nun unter dem Punkt "Zusätzliche Boardverwalter-URLs:" die folgenden Zeilen eintragen. https://arduino.esp8266.com/stable/package_esp8266com_index.json https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json Bei der Gelegenheit gleich noch die "Compiler Warnungen" auf "Alle" stellen. IDE und Master Ordner schließen. Jetzt zwei Kopien vom Master Ordner anlegen und entsprechend umbenennen. Arduino_1.8.19_Master Arduino_1.8.19_core_2.6.3 Arduino_1.8.19_core_2.7.4 Arduino_1.8.19_core_3.1.0 Anschließend die IDE in den beiden neuen Ordnern öffnen und im Menü Werkzeuge/Board/Boardverwalter den Boardverwalter öffnen. Oben hinter "Typ" esp reinschreiben. Esp Core Version einstellen und Installieren. Den Master Ordner bewahren wir für die kommende Core Version 3.1.1 auf.
void loop() {
if (static auto once {0}; !once++) Serial.println("Einmalig auch in for/while Schleifen.");
}
kurz und prägnant (veraltet ab C++17)
void loop() {
static bool once {0};
if (!once++) Serial.println("Einmalig"); // (bool Operator ++) veraltet ab EspCoreVersion 3.0.0.
}
void funktion() {
Serial.println("Wird bei jedem Aufruf ausgeführt!"); // Ausgabe nur zur Kontrolle, ansonsten kann das weg.
constexpr uint8_t x = {5};
if (static uint8_t viewsCount; !(++viewsCount, viewsCount %= x)) Serial.printf("Wird aller %u Aufrufe ausgeführt!\n", x);
}
C++14 (vor ESP Core 3.x.x)
void funktion() {
Serial.println("Wird bei jedem Aufruf ausgeführt!"); // Ausgabe nur zur Kontrolle, ansonsten kann das weg.
constexpr uint8_t x = {5};
static uint8_t viewsCount;
if (!(++viewsCount, viewsCount %= x)) Serial.printf("Wird aller %u Aufrufe ausgeführt!\n", x);
}
const byte LED_PIN = LED_BUILTIN;
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, millis() % 1000 >= 500);
}
Mit unterschiedlichen an und aus Zeiten.
const byte LED_PIN = LED_BUILTIN;
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
const uint32_t TIME_OFF = 200; // 200 ms aus // 6e4 für 60 Sekunden aus // 18e5 für 30 Minuten aus
const uint32_t TIME_ON = 400; // 400 ms an // 3e4 für 30 Sekunden an // 36e5 für 60 Minuten an
digitalWrite(LED_PIN, millis() % (TIME_OFF + TIME_ON) >= TIME_ON);
}
Zwei mit verschiedenen Zeiten.
const byte LED_SHORT = 2;
const byte LED_LONG = 16;
void setup() {
pinMode(LED_SHORT, OUTPUT);
pinMode(LED_LONG, OUTPUT);
}
void loop() {
digitalWrite(LED_SHORT, millis() % 1000 >= 500); // 500ms an/aus
digitalWrite(LED_LONG, millis() % 2000 >= 1000); // 1 s an/aus
}
Wechselblinker
const byte LED_LEFT = 2;
const byte LED_RIGHT = 16;
void setup() {
pinMode(LED_LEFT, OUTPUT);
pinMode(LED_RIGHT, OUTPUT);
}
void loop() {
digitalWrite(LED_LEFT, !(millis() % 1000 >= 500));
digitalWrite(LED_RIGHT, millis() % 1000 >= 500);
}
Tag, Monat, Jahr prüfen
Datum_pruefen.ino
bool checkDate(uint8_t d, uint8_t m, uint16_t y) {
uint8_t daysPerMonth[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if ((!(y % 4) && y % 100) || !(y % 400)) daysPerMonth[2]++;
bool valid = d <= daysPerMonth[m] && d && m <= 12 && m && y;
Serial.printf("Datum %02d.%02d.%d ist %sgültig.\n", d , m , y , valid ? "" : "un");
return valid;
}
void setup() {
Serial.begin(115200);
Serial.println();
checkDate(29, 2, 2020); //day, month, year
}
void loop() {}
Testausgabe:
Datum 29.02.2020 ist gültig.
Ein- und Ausschalten über den Tageswechsel
Tageswechsel.ino
void setup() {
Serial.begin(115200);
delay(300);
Serial.printf("\nSketchname: %s\t Hochgeladen: %s\n\n", __FILE__, __TIMESTAMP__);
uint16_t onTime = 23 * 60 + 11; // 23:11 Uhr Einschaltzeitpunkt
uint16_t offTime = 06 * 60 + 05; // 06:05 Uhr Ausschaltzeitpunkt
const uint16_t currentTime = 3 * 60 + 21; // 03:21 Uhr Aktuelle Uhrzeit
bool switched = (onTime < offTime) ? (currentTime >= onTime && currentTime < offTime) : (currentTime >= onTime || currentTime < offTime);
Serial.printf("Um %02d:%02d Uhr ist der Ausgang %sgeschaltet.\n", currentTime / 60 % 100, currentTime % 60, switched ? "ein" : "aus");
}
void loop() {}
Testausgabe:
Um 03:21 Uhr ist der Ausgang eingeschaltet.
String Zeichen ersetzen
String_replace.ino
void setup() {
String incoming = "Nach:und/kommt\"er;hier\\";
Serial.begin(115200);
Serial.println();
Serial.println(incoming);
for (auto& c : {'"', '/', ':', ';', '\\'}) for (auto& e : incoming) if (e == c) e = '_'; // Ersetzt alle unerwünschten Zeichen
Serial.println(incoming);
}
void loop() {}
Testausgabe:
Nach:und/kommt"er;hier\ Nach_und_kommt_er_hier_
Datentypen Esp8266 Core für Arduino C++
bool, boolean bool: 1 Byte Min: 0 Max: 1 ------------- int8_t, char, signed char Size: 1 Byte Min: -128 Max: 127 ------------- uint8_t, unsigned char, byte Size: 1 Byte Min: 0 Max: 255 ------------- int16_t, short, signed short, short int, signed short int, char16_t Size: 2 Byte Min: -32768 Max: 32767 ------------- uint16_t, unsigned short, word Size: 2 Byte Min: 0 Max: 65535 ------------- int32_t, long, int, signed long, signed int, long int, signed long int, char32_t Size: 4 Byte Min: -2147483648 Max: 2147483647 ------------- uint32_t, uint, unsigned long, unsigned int, unsigned long int Size: 4 Byte Min: 0 Max: 4294967295 ------------- int64_t, long long, signed long long, long long int, signed long long int, intmax_t Size: 8 Byte Min: -9223372036854775808 Max: 9223372036854775807 ------------- uint64_t, unsigned long long, unsigned long long int, uintmax_t Size: 8 Byte Min: 0 Max: 18446744073709551615 ------------- float Size: 4 Byte Min: 1.17549e-38 Max: 3.40282e+38 ------------- double Size: 8 Byte Min: 2.22507e-308 Max: 1.79769e+308
Sketch Datentypen Esp8266
Datentypen.ino
#include <limits.h>
#include <float.h>
#include <iostream> // alle Bibliotheken sind im Esp Core enthalten
using namespace std;
void setup() {
Serial.begin(115200);
delay(100);
Serial.printf("\n\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
(__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());
cout << "\n Datentypen Esp8266 C++\n" << endl;
cout << " bool, boolean" << endl;
cout << " bool: " << sizeof(bool) << " Byte \t" << "Min: " << false << "\t" << "Max: " << true << endl;
cout << "\t-------------" << endl;
cout << " int8_t, char, signed char" << endl;
cout << " Size: " << sizeof(char) << " Byte \t" << "Min: " << SCHAR_MIN << "\t" << "Max: " << SCHAR_MAX << endl;
cout << "\t-------------" << endl;
cout << " uint8_t, unsigned char, byte" << endl;
cout << " Size: " << sizeof(unsigned char) << " Byte \t" << "Min: " << "0" << "\t\t" << "Max: " << UCHAR_MAX << endl;
cout << "\t-------------" << endl;
cout << " int16_t, short, signed short, short int, signed short int, char16_t" << endl;
cout << " Size: " << sizeof(short) << " Byte \t" << "Min: " << INT16_MIN << "\t" << "Max: " << INT16_MAX << endl;
cout << "\t-------------" << endl;
cout << " uint16_t, unsigned short, word" << endl;
cout << " Size: " << sizeof(unsigned short) << " Byte \t" << "Min: " << "0" << "\t\t" << "Max: " << USHRT_MAX << endl;
cout << "\t-------------" << endl;
cout << " int32_t, long, int, signed long, signed int, long int, signed long int, char32_t" << endl;
cout << " Size: " << sizeof(long) << " Byte \t" << "Min: " << INT32_MIN << "\t" << "Max: " << INT32_MAX << endl;
cout << "\t-------------" << endl;
cout << " uint32_t, uint, unsigned long, unsigned int, unsigned long int" << endl;
cout << " Size: " << sizeof(unsigned long) << " Byte \t" << "Min: " << numeric_limits<uint>::min() << "\t\t\t" << "Max: " << numeric_limits<uint>::max() << endl;
cout << "\t-------------" << endl;
cout << " int64_t, long long, signed long long, long long int, signed long long int, intmax_t" << endl;
cout << " Size: " << sizeof(long long) << " Byte \t" << "Min: " << INT64_MIN << "\t" << "Max: " << INT64_MAX << endl;
cout << "\t-------------" << endl;
cout << " uint64_t, unsigned long long, unsigned long long int, uintmax_t" << endl;
cout << " Size: " << sizeof(unsigned long long) << " Byte \t" << "Min: " << "0" << "\t\t\t\t" << "Max: " << UINT64_MAX << endl;
cout << "\t-------------" << endl;
cout << " float" << endl;
cout << " Size: " << sizeof(float) << " Byte \t" << "Min: " << FLT_MIN << "\t" << "Max: " << FLT_MAX << endl;
cout << "\t-------------" << endl;
cout << " double" << endl;
cout << " Size: " << sizeof(double) << " Byte \t" << "Min: " << DBL_MIN << "\t" << "Max: " << DBL_MAX << endl;
}
void loop() {}
Ein Funktionstemplate ist eine Vorlage, die Funktionen erzeugt der Compiler für die jeweiligen Datentypen.
Die Serielle Ausgabe innerhalb der Funktion ist nur zur Demonstration.
2D_Array.ino
#include <iostream> // Bibliothek ist im Esp Core enthalten.
int intToUse[][5] = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}};
float floatToUse[][6] = {{1.56, 2.67, 3.78, 4.89, 5.90, 6.12}, { -6.1, -7.2, -8.3, -9.4, -10.5, -11.6}, {11, 12, 13, 14, 15, 16}};
char charToUse[][4] = {{'a', 'b', 'c', 'd'}, {'A', 'B', 'C', 'D'}, {'1', '2', '3', '4'}};
template <typename T, size_t column, size_t row> T toPrintOut(T (&arr)[column][row]) {
for (auto &columns : arr) {
for (auto &value : columns) {
std::cout << value << ", ";
}
std::endl (std::cout);
}
}
void setup() {
Serial.begin(115200);
std::cout << "\n\n";
std::cout << "Funktions-Template mit int" << std::endl;
toPrintOut(intToUse);
std::cout << "\nFunktions-Template mit float" << std::endl;
toPrintOut(floatToUse);
std::cout << "\nFunktions-Template mit char" << std::endl;
toPrintOut(charToUse);
}
void loop() {}
Testausgabe:
Funktions-Template mit int 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, Funktions-Template mit float 1.56, 2.67, 3.78, 4.89, 5.9, 6.12, -6.1, -7.2, -8.3, -9.4, -10.5, -11.6, 11, 12, 13, 14, 15, 16, Funktions-Template mit char a, b, c, d, A, B, C, D, 1, 2, 3, 4,
Universelle Funktionen für Array aller Datentypen des Esp.
Template.ino
// Template Funktion größten Wert aus Array ermitteln
template <typename T, size_t size> T maxRead(const T (&arr)[size]) {
T maxValue {arr[0]};
for (auto &value : arr) maxValue = max(maxValue, value);
return maxValue;
}
// Template Funktion kleinsten Wert aus Array ermitteln
template <typename T, size_t size> T minRead(const T (&arr)[size]) {
T minValue {arr[0]};
for (auto &value : arr) minValue = min(minValue, value);
return minValue;
}
// Template Funktion Durchschnitt aus Array ermitteln
template <typename T, size_t size> T averageRead(const T (&arr)[size]) {
double average {0};
for (auto &value : arr) average += static_cast<double>(value) / size;
return std::numeric_limits<T>::is_integer ? round(average) : average;
}
const char charArray[] {'%', 42, '!', 40};
const int8_t int8Array[] {5, 3, 2, 4, 5, 1, 3, 2, 4, 5, -1, 2, 3, 4, 2, 1, 6, 3, 2, 4, 1, 5, 3, 2, 4, 2, 5, 3, 2, 4, 3, 5, 1, 1, 2};
const uint8_t uint8Array[] {67, 107, 115, 123, 103, 116, 112, 175, 93, 4, 91, 99, 253, 111, 119, 118, 108, 89, 121, 77, 79, 97, 87, 59, 127, 126, 125, 124, 123};
const int32_t int32Array[] { -2134567890, 1234567890, 987654321, -69567433, 981, 483609};
const uint64_t uint64Array[] {2113720368549745289, 6134567890, 1337203685477587};
const float floatArray[] { -1.55, 8.94, 14.27, -5.63, 10.42, 2.38, 87.91, 3.39, 4.73};
void setup() {
Serial.begin(115200);
delay(100);
Serial.printf("\n\n%s\n\n", __TIMESTAMP__);
Serial.printf("char max:\t%4d\n", maxRead(charArray));
Serial.printf("char min:\t%4d\n", minRead(charArray));
Serial.printf("char mittel:\t%4d\n", averageRead(charArray));
Serial.printf("\nint8 max:\t%4d\n", maxRead(int8Array));
Serial.printf("int8 min:\t%4d\n", minRead(int8Array));
Serial.printf("int8 mittel:\t%4d\n", averageRead(int8Array));
Serial.printf("\nuint8 max:\t%4d\n", maxRead(uint8Array));
Serial.printf("uint8 min:\t%4d\n", minRead(uint8Array));
Serial.printf("uint8 mittel:\t%4d\n", averageRead(uint8Array));
Serial.printf("\nfloat max:\t%11f\n", maxRead(floatArray));
Serial.printf("float min:\t%11f\n", minRead(floatArray));
Serial.printf("float mittel:\t%11f\n", averageRead(floatArray));
Serial.printf("\nint32 max:\t%+11d\n", maxRead(int32Array));
Serial.printf("int32 min:\t%+11d\n", minRead(int32Array));
Serial.printf("int32 mittel:\t%+11d\n", averageRead(int32Array));
Serial.printf("\nuint64 max:\t\t%19lld\n", maxRead(uint64Array));
Serial.printf("uint64 min:\t\t%19lld\n", minRead(uint64Array));
Serial.printf("uint64 mittel:\t%19lld\n", averageRead(uint64Array));
}
void loop() {}
Testausgabe:
Wed Apr 29 11:46:08 2020 char max: 42 char min: 33 char mittel: 38 int8 max: 6 int8 min: -1 int8 mittel: 3 uint8 max: 253 uint8 min: 4 uint8 mittel: 109 float max: 87.910004 float min: -5.630000 float mittel: 13.873334 int32 max: +1234567890 int32 min: -2134567890 int32 mittel: +3095246 uint64 max: 2113720368549745289 uint64 min: 6134567890 uint64 mittel: 705019192789930368
Speichern und einlesen einer Struktur
SaveStruct.ino
#include <LittleFS.h>
// Struktur deklarieren
struct Collection {
bool button;
float currentTemp;
float minTemp;
float maxTemp;
char minTime[9];
char maxTime[9];
};
// Funktion zum speichern der Struktur in einer Datei im Dateisystem des Esp8266
bool toSave(Collection &departure) {
File file = LittleFS.open("/stream.dat", "w");
if (file) {
file.write(reinterpret_cast<byte*>(&departure), sizeof(departure)); // Serialisierung
file.close();
return true;
}
return false;
}
// Funktion zum einlesen der Daten aus der Datei
bool toRead(Collection &destination) {
File file = LittleFS.open("/stream.dat", "r");
if (file) {
file.read(reinterpret_cast<byte*>(&destination), sizeof(destination)); // Deserialisierung
file.close();
return true;
}
return false;
}
void setup() {
Serial.begin(115200);
delay(100);
Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
(__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 10, ESP.getFullVersion().c_str());
// Dateisystem initialisieren
LittleFS.begin();
// eine Variable von Typ der Struktur anlegen
Collection departure;
// Testdaten in die Struktur schreiben
departure.button = true;
departure.currentTemp = 8.4;
departure.minTemp = -2.3;
departure.maxTemp = 15.9;
strcpy(departure.minTime, "10:29:04");
strcpy(departure.maxTime, "06:55:32");
// Funktion zum speichern aufrufen
bool result = toSave(departure);
Serial.printf("Datei schreiben %s!\n", result ? "erfolgreich" : "fehlgeschlagen");
}
void loop() {
static auto once {0};
if (!once++) {
// eine Variable von Typ der Struktur anlegen
struct Collection destination;
// Funktion zum einlesen aufrufen
bool result = toRead(destination);
Serial.printf("Datei lesen %s!\n", result ? "erfolgreich" : "fehlgeschlagen");
// Testdaten Seriell ausgeben
Serial.println("\nAusgabe:");
Serial.println(destination.button);
Serial.println(destination.currentTemp);
Serial.println(destination.minTemp);
Serial.println(destination.maxTemp);
Serial.println(destination.minTime);
Serial.println(destination.maxTime);
}
}
Testausgabe:
Datei schreiben erfolgreich! Datei lesen erfolgreich! Ausgabe: 1 8.40 -2.30 15.90 10:29:04 06:55:32
Darin ist genug zu lernen, probieren und neu zusammen setzen um eigene Projekte zu kreieren für lange Zeit.
Einfach nur Spitze. Schade ist nur das maximum 3 Sterne vergeben werden können. Ausgegangen von der Standard Bewertung sollten 5 Sternen für dich möglich sein.
Etwas anderes. Ich bin auf deine Seite gekommen weil ich ein Alten Heizungs-Thermostat durch ein ESP XXX ersetzen möchte wobei mir viele kleine Feature eingefallen sind. Ein B.z wäre wenn ein Abend mal länger wird die Heizung durch druck auf eine Taste +1 die Zeit um eine Stunden verlängern.
Wenn möglich würde mich eine Kontakt Aufnahme, für ein Paar Ideen Auszutauschen, sehr freuen.
Antwort:
Für einen Austausch, nutze bitte das Kontaktformular.
Gruß Fips
Herzlichen Dank Ähre ))
Antwort:
Danke, für dein Feedback.
Gruß Fips
ich möchte Deine Template.ino[Durchschnitt] verwenden. Meine Daten sind aber nicht in einem const[array], sondern können unterschiedliche Größen haben. Also z.B. 150 Daten, 100 Daten, 120 Daten usw. Die Rohdaten stammen vom 'analogRead'. Kann man das Template für diese Flexibilität umschreiben ?
Vielen Dank.
Antwort:
Entweder du machst das Array groß genug und füllst es mit Null auf oder verwendest die C++ Containers library ( zB.: std::vector), was ich vorziehen würde.
Gruß Fips
hier kann ich noch viel lernen (und gebrauchen) !!
MB
Antwort:
Danke, für dein Feedback!
Gruß Fips
Hast du auch ein einen Ringpuffer um neuste Daten zu speichern und die ältesten zu löschen?
Antwort:
Im TX23 Tab sind 6 "first in first out" Puffer enthalten.
Gruß Fips
Diese Seite ist der Hammer.
Gruss
Antwort:
Danke, für dein Feedback!
Gruß Fips