Hallo,
Ich habe seither nur mit dem Arduino gebastelt und programmiert,
nun möchte ich auch die NodeMCU verwenden.
Ich möchte die NodeMCU unter Linux (Opensuse 13.1) und der Arduino IDE 1.6.5 programmieren.
Ist es unter Linux egal ob die NodeMCU einen CP2102 oder CH340G verwendet?
Nach einigen Anleitungen, sollte die NodeMCU den ESP-12E haben.
Ich habe mal bei ebay geschaut.
Bei diesen beiden kann ich nicht erkennen ob ein ESP-12E verwendet wird.
NodeMcu Lua CH340G ESP8266 Wireless WIFI Internet Development Module DE TE390
NodeMCU Lua WIFI IOT Node EntwicklungsBoard ESP8266 micro USB 32bit Arduino
Edit:
Ich habe inzwischen einiges gelesen, demnach dürfte es egal sein welche NodeMCU ich nehme.
Wenn ich mit der Arduino IDE 1.6.5 die NodeMCU programmieren will, muß ich dies
http://arduino.esp8266.com/stable/package_esp8266com_index.json
unter Datei - Voreinstellungen eintragen.
Hier
http://arduino.esp8266.com/versions/1.6.5-947-g39819f0/doc/reference.html (http://arduino.esp8266.com/versions/1.6.5-947-g39819f0/doc/reference.html)
steht, daß für den ESP8266 eine eigene EEPROM library verwendet wird.
Kann ich dann mit der Arduino IDE noch was für den Arduino unter Verwendung der EEPROM library, programmieren?
Gruß Ralf
Klar,
der verwendete Core wird ja mit jedem Board "umgeschaltet".
Wenn ein du ESP - BOARD auswählst kompiliert Arduino mit dem passenden Core für die ESP-Architektur.
Das ist es ja, was Arduino ausmacht, für dich sehen die verwendeten Befehle immer gleich aus.
Arduino "übersetzt" diese dann für die entsprechende Architektur mittels der verwendeten Cors.
Damit sollte, zumindest theoretisch, ein und der selbe Sketch auf einem Atmel wie auf einem ESP laufen.
Gruß
Pf@nne
Zitat von: Pf@nne am 24 April 2016, 06:07:32
der verwendete Core wird ja mit jedem Board "umgeschaltet".
Wenn ein du ESP - BOARD auswählst kompiliert Arduino mit dem passenden Core für die ESP-Architektur.
Danke, damit ist es klar.
Ich werde diesen hier kaufen, der müsste passen:
http://www.ebay.de/itm/NodeMcu-Lua-CH340G-ESP8266-Wireless-WIFI-Internet-Development-Module-DE-TE390-/191816004111?hash=item2ca91ff20f:g:TqUAAOSw~OVW1B7g (http://www.ebay.de/itm/NodeMcu-Lua-CH340G-ESP8266-Wireless-WIFI-Internet-Development-Module-DE-TE390-/191816004111?hash=item2ca91ff20f:g:TqUAAOSw~OVW1B7g)
Hier steht
http://arduino.esp8266.com/versions/1.6.5-947-g39819f0/doc/reference.html
The Program memory features work much the same way as on a regular Arduino; placing read only data and strings in read only memory
and freeing heap for your application. The important difference is that on the ESP8266 the literal strings are not pooled.
This means that the same literal string defined inside a F("") and/or PSTR("") will take up space for each instance in the code.
So you will need to manage the duplicate strings yourself.
Sehe ich das richtig, daß dies für mich nicht relevant ist, wenn ich nur F("") benutze.
Z.B. Serial.println(F("Unsupported command"));
Gruß Ralf
wenn ich mich recht erinnere (LaCrosseGateway (https://forum.fhem.de/index.php/topic,43672.0.html)), dann sind die NodeMCUs mit CH340G problematischer, als die mit CP2102.
ich verwende diesen (http://www.amazon.de/Diymall-NodeMCU-Devkit-CP2102-Apples/dp/B00XJG7GEK/ref=sr_1_5?ie=UTF8&qid=1461491528&sr=8-5&keywords=NodeMCU).
PS: ich interessiere mich für signalduino auf esp8266-Basis.
Zitat von: habeIchVergessen am 24 April 2016, 11:54:41
PS: ich interessiere mich für signalduino auf esp8266-Basis.
Mit dem ESP-8266 als WiFi-Serial Bridge funktioniert es bereits:
http://www.hjgode.de/wp/2015/11/05/fhem-serielle-gerat-uber-wifi-anbinden/ (http://www.hjgode.de/wp/2015/11/05/fhem-serielle-gerat-uber-wifi-anbinden/)
Sidey hat vor zu testen ob der signalduino auch auf der NodeMCU läuft.
Die Wahrscheinlichkeit, daß es sauber funktioniert ist aber eher gering:
https://forum.fhem.de/index.php/topic,38831.msg438680.html#msg438680 (https://forum.fhem.de/index.php/topic,38831.msg438680.html#msg438680)
Gruß Ralf
Zitat von: Ralf9 am 24 April 2016, 11:35:03
Ich werde diesen hier kaufen, der müsste passen:
http://www.ebay.de/itm/NodeMcu-Lua-CH340G-ESP8266-Wireless-WIFI-Internet-Development-Module-DE-TE390-/191816004111?hash=item2ca91ff20f:g:TqUAAOSw~OVW1B7g (http://www.ebay.de/itm/NodeMcu-Lua-CH340G-ESP8266-Wireless-WIFI-Internet-Development-Module-DE-TE390-/191816004111?hash=item2ca91ff20f:g:TqUAAOSw~OVW1B7g)
Ich habe heute die nodemcu erhalten.
Das flashen mit der Arduino IDE 1.6.5 hat auf Anhieb problemlos funktioniert. Zu was wird die flashtaste benötigt?
Die Probleme mit der static IP konnte ich nicht nachvollziehen. Bei mir funktioniert es mit der static IP problemlos.
Ich habe mir zum Testen einen testsketch geschrieben.
Dabei ist mir aufgefallen, daß "server.println" nicht funktioniert. Mache ich da evtl was falsch?
#include <ESP8266WiFi.h>
const char* ssid = "***";
const char* pass = "***";
int var = 0;
int welcome = 0;
byte ip[] = { 192, 168, 0, x };
byte gateway[] = { 192, 168, 0, x };
byte subnet[] = { 255, 255, 255, 0 };
WiFiServer server(1000);
WiFiServer server1(23); // für debug ausgabe
WiFiClient client;
WiFiClient client1; // für debug ausgabe
void setup() {
WiFi.begin(ssid, pass);
WiFi.config(ip, gateway, subnet);
uint8_t i = 0;
while (WiFi.status() != WL_CONNECTED && i++ < 20) delay(500);
if(i == 21){
while(1) delay(500);
}
server.begin();
server1.begin();
server.setNoDelay(true);
server1.setNoDelay(true);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
}
void loop()
{
//check if there are any new clients
if (server.hasClient()){
if (!client || !client.connected()) {
if(client) {
client.stop();
}
client = server.available();
client.flush();
}
}
if (server1.hasClient()){ // debug client
if (!client1 || !client1.connected()) {
if(client1) {
client1.stop();
}
client1 = server1.available();
client1.flush();
}
}
if (client && client.connected()){
if(client.available()){
if (welcome == 0) {
client.println("welcome nodemcu");
client1.println("welcome debug nodemcu");
welcome = 1;
}
var = client.read();
if (var == 97) { // a
digitalWrite(LED_BUILTIN, HIGH);
client.println("led aus");
client1.println("LED aus");
} else if (var == 98) { // b
digitalWrite(LED_BUILTIN, LOW);
client.println("led ein");
} else if (var == 99) { // c
client.print("Free Heap RAM: ");
client.println(ESP.getFreeHeap());
} else if (var == 100) { // d
welcome = 0;
client.println("welcome = 0");
}
}
}
}
Gruß Ralf
Ich habe mir mit dieser Vorlage
https://github.com/kc-GitHub/HM485-Lib
ein HM-Wired Modul gebastelt, das direkt über Lan angebunden ist.
Nun bin ich gerade dabei, anpassungen für die NodeMCU vorzunehmen. Einiges funktioniert schon.
Siehe Anlage:
Der HBW_IO_SW_HBW8555631 ist ein Arduino Mega 2560 mit ethernet shield.
Der HBW_IO_SW_ESP8266000 ist eine NodeMCU.
Ich habe noch ein paar Fragen/Probleme:
Da die NodeMCU nur sehr wenig GPIOs hat, möchte ich für die "keys" den MCP23017 mit der "Adafruit_MCP23017_Arduino_Library" verwenden.
Ich möchte dann die handleKeys Routine nur noch alle 50ms aufrufen. Hat dies irgendwelche Nachteile?
Momentan wird sie noch bei jedem loop durchlauf aufgerufen.
// Tastenkey, es sind 12 Tasten definiert
void handleKeys() {
// millis() zum Zeitpunkt eines Tastendrucks
// verwendet zum Entprellen, lange Tastendruecke und wiederholtes Senden langer Tastendruecke
static unsigned long keyPressedMillis[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
static byte keyPressNum[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
static unsigned long lastSentLong[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
boolean portStat;
unsigned long now = millis();
for(byte i = 0; i < NUM_KEYS; i++) {
// INPUT_LOCKED?
if(!config.keys[i].input_locked) continue; // inverted logic, locked = 0
portStat = bitRead(keyPortStatus[i/8],i%8);
if (!config.keys[i].input_inverted) { // inverted
portStat = !portStat;
}
if (portStat) { // 1 = Taste nicht gedrueckt
// Taste war auch vorher nicht gedrueckt kann ignoriert werden
// Taste war vorher gedrueckt?
if(keyPressedMillis[i]) {
// entprellen, nur senden, wenn laenger als 50ms gedrueckt
// aber noch kein "long" gesendet
if(now - keyPressedMillis[i] >= 50 && !lastSentLong[i]) {
keyPressNum[i]++;
hmwmodule->broadcastKeyEvent(i + CHANNEL_START_KEYS, keyPressNum[i]);
triggerPeeringTime(i, 255, 0); // 0 = short
}
keyPressedMillis[i] = 0;
}
}
else { // Taste gedrueckt
if(keyPressedMillis[i]) { // Taste war vorher schon gedrueckt
// muessen wir ein "long" senden?
if(lastSentLong[i]) { // schon ein LONG gesendet
if(now - lastSentLong[i] >= 300) { // alle 300ms wiederholen
// keyPressNum nicht erhoehen
lastSentLong[i] = now ? now : 1; // der Teufel ist ein Eichhoernchen
hmwmodule->broadcastKeyEvent(i + CHANNEL_START_KEYS, keyPressNum[i], true);
}
}
else if (millis() - keyPressedMillis[i] >= long(config.keys[i].long_press_time * 100)) {
// erstes LONG
keyPressNum[i]++;
lastSentLong[i] = millis();
hmwmodule->broadcastKeyEvent(i + CHANNEL_START_KEYS,keyPressNum[i], true);
triggerPeeringTime(i, 255, 1); // 1 = long
}
}
else {
// Taste war vorher nicht gedrueckt
keyPressedMillis[i] = now ? now : 1; // der Teufel ist ein Eichhoernchen
lastSentLong[i] = 0;
}
}
} // for
}
Sehe ich das richtig, daß ich für das EEPROM.read das
EEPROM.begin(1024);
nur einmal im setup() aufrufen muß?
Mit der folgenden readConfig Routine wird die "struct hmw_config" eingelesen.
Bei der NodeMCU musste ich den ptr korrigieren (ptr += 3;). Beim Arduino ist dies nicht notwendig.
Hat dafür jemand eine Erklärung?
hmw_config config;
void readConfig(){
byte* ptr;
printConfigFlag = true;
// EEPROM lesen
ptr = (byte*)(&config);
ptr += 3;
for(int address = 0; address < (sizeof(config)-3); address++){
*ptr = EEPROM.read(address + 0x01);
ptr++;
}
..
}
Hier ist ein Auszug aus der HMWRegister.h
// Sensor
struct hmw_config_sensor {
byte input_locked :1; // 0=LOCKED, 1=UNLOCKED
byte input_inverted :1; // 0=inverted 1=normal
byte input_pullup :1; // 1=PULLUP
byte :5; //
};
// Taster
struct hmw_config_key {
byte input_type :1; // 0=SWITCH, 1=PUSHBUTTON
byte input_locked :1; // 0=LOCKED, 1=UNLOCKED
byte input_inverted :1; // 0=inverted 1=normal
byte input_pullup :1; // 1=PULLUP
byte :4;
byte long_press_time; // in sec/10
};
struct hmw_config {
byte logging_time; // 0x01
long central_address; // 0x02 - 0x05
byte direct_link_deactivate:1; // 0x06
byte :7;
hmw_config_sensor sensors[16]; // 0x07 - 0x16
hmw_config_key keys[16]; // 0x17 - 0x36
}
Zitat von: Ralf9 am 26 Mai 2016, 22:53:28
Da die NodeMCU nur sehr wenig GPIOs hat, möchte ich für die "keys" den MCP23017 mit der "Adafruit_MCP23017_Arduino_Library" verwenden.
Ich möchte dann die handleKeys Routine nur noch alle 50ms aufrufen. Hat dies irgendwelche Nachteile?
Momentan wird sie noch bei jedem loop durchlauf aufgerufen.
Da dies anscheinend keine Nachteile hat, habe ich es nun umgestellt, daß die handleKeys Routine nur noch alle 50ms aufrufen und der MCP23017 verwendet wird.
Das müsste so jetzt passen:
// Tastenkey, es sind max 12 Tasten definiert
void handleKeys() {
static byte keyPressed50ms[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
static byte keyPressNum[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
static byte lastSentLong[2] = {0,0}; // wurde bereits long gesendet?
static byte flag[2] = {0,0};
boolean portStat;
byte i;
// KEY_CHANNEL_PORTS
// for(i = 0; i < NUM_KEYS; i++){
// // Pin lesen und Bit in portStatus setzen
// bitWrite(keyPortStatus[i/8],i%8,digitalRead(keyChannelPorts[i]));
// }
keyPortStatus[0] = mcp.readGPIO(0);
if (NUM_KEYS > 8) {
keyPortStatus[1] = mcp.readGPIO(1);
}
//for(i = 0; i < NUM_KEYS; i++) {
// bitWrite(keyPortStatus[i/8],i%8, bitRead(a,i);
//}
for(i = 0; i < NUM_KEYS; i++) {
// INPUT_LOCKED?
if(!config.keys[i].input_locked) continue; // inverted logic, locked = 0
portStat = bitRead(keyPortStatus[i/8],i%8);
if (!config.keys[i].input_inverted) { // inverted
portStat = !portStat;
}
if (portStat) { // 1 = Taste nicht gedrueckt (negative Logik wegen INPUT_PULLUP)
// Taste war auch vorher nicht gedrueckt kann ignoriert werden
// Taste war vorher gedrueckt?
if(keyPressed50ms[i]) {
// entprellen, nur senden, wenn laenger als 50ms gedrueckt, aber noch kein "long" gesendet
if (!bitRead(lastSentLong[i/8], i%8)) { // war kein long
if(keyPressed50ms[i] >= 2) {
keyPressNum[i]++;
keyPressed50ms[i] = 0;
hmwmodule->broadcastKeyEvent(i + CHANNEL_START_KEYS, keyPressNum[i]);
triggerPeeringTime(i, 255, 0); // 0 = short
} else {
keyPressed50ms[i] = 2;
}
} else { // war long
keyPressed50ms[i] = 0;
bitClear(lastSentLong[i/8], i%8);
}
} else {
bitClear(flag[i/8], i%8); // Flag = 0
}
} // Taste gedrueckt
else {
if(config.keys[i].input_type) { // pushbutton
// Taste war vorher schon gedrueckt
if(keyPressed50ms[i]) {
// muessen wir ein "long" senden?
if(bitRead(lastSentLong[i/8], i%8)) { // schon ein LONG gesendet
if(keyPressed50ms[i] >= 6) { // alle 300ms wiederholen
// keyPressNum nicht erhoehen
keyPressed50ms[i] = 0;
hmwmodule->broadcastKeyEvent(i + CHANNEL_START_KEYS, keyPressNum[i], true); // true = long
}
} else if (keyPressed50ms[i] >= (config.keys[i].long_press_time * 2)) {
// erstes LONG
keyPressNum[i]++;
keyPressed50ms[i] = 0;
bitSet(lastSentLong[i/8], i%8);
hmwmodule->broadcastKeyEvent(i + CHANNEL_START_KEYS, keyPressNum[i], true); // true = long
triggerPeeringTime(i, 255, 1); // 1 = long
}
keyPressed50ms[i]++;
} else {
// Taste war vorher nicht gedrueckt
keyPressed50ms[i] = 1;
bitClear(lastSentLong[i/8], i%8);
}
} else { // type = switch
if(!keyPressed50ms[i]) {
if (bitRead(flag[i/8], i%8) == 1) { // flag
bitClear(flag[i/8], i%8); // flag = 0
keyPressNum[i]++;
keyPressed50ms[i] = 1;
hmwmodule->broadcastKeyEvent(i + CHANNEL_START_KEYS, keyPressNum[i]);
triggerPeeringTime(i, 255, 0); // 0 = short
} else {
bitSet(flag[i/8], i%8); // flag = 1
}
}
} // type
}
} // for
}
Nun habe ich alles was ich wollte hinbekommen.
Die nodemcu ist über wlan mit dem HM-wired Protokoll angebunden.
Es sind max 16 Sensoren für Kontakte und max 16 Tastereingänge (short/long) möglich.
Es sind auch bis zu 8 Ausgänge möglich. Ich habe auch ein vereinfachtes internes peering eingebaut.
Bei Bedarf sind auch bis zu 4 Rollos möglich.
Gruß Ralf