Portable Arduino IDE einrichten
Eine Aktion einmalig ausführen
Eine Aktion nur bei jedem x-ten Aufruf einer Funktion ausführen
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() {
static auto once {0};
if (!once++) Serial.println("Einmalig");
}
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.
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
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