-
Notifications
You must be signed in to change notification settings - Fork 516
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WiFi] added support for ESP32 architecture and XIAO ESP32C3 board #512
base: main
Are you sure you want to change the base?
Changes from 1 commit
7d6ada1
7a6dd82
9651a7c
dde9fd9
ad79f15
4567db4
08325d1
af2e9aa
90ac082
44a8788
b3a78d5
d072c0a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
Firmata.h - Firmata library v2.5.8 - 2018-04-15 | ||
Firmata.h - Firmata library v2.5.10 - 2023-12-16 | ||
Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved. | ||
Copyright (C) 2009-2017 Jeff Hoefs. All rights reserved. | ||
|
||
|
@@ -38,7 +38,9 @@ | |
//#define INPUT 0x00 // defined in Arduino.h | ||
//#define OUTPUT 0x01 // defined in Arduino.h | ||
// DEPRECATED as of Firmata v2.5 | ||
#define ANALOG 0x02 // same as PIN_MODE_ANALOG | ||
#ifndef ARDUINO_ARCH_ESP32 | ||
#define ANALOG 0x02 // same as PIN_MODE_ANALOG | ||
#endif | ||
Comment on lines
+41
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain why this is necessary again? Maybe we can figure out a creative solution to work around your need. My fear is that you are going to break backward compatibility with this change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had to do a similar change in ConfigurableFirmata, as the problem is that there's a conflicting definition of ANALOG (as well as INPUT and OUTPUT) in the ESP32 headers. IIRC, the values don't even match, so setting the pin mode could strangely fail, depending on which of the definitions is in scope at the calling place. But I think the right solution is to call this PIN_MODE_ANALOG, to avoid further ambiguities. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I see it. It's in |
||
#define PWM 0x03 // same as PIN_MODE_PWM | ||
#define SERVO 0x04 // same as PIN_MODE_SERVO | ||
#define SHIFT 0x05 // same as PIN_MODE_SHIFT | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ | |
|
||
See file LICENSE.txt for further informations on licensing terms. | ||
|
||
Last updated August 17th, 2017 | ||
Last updated December 17th, 2023 | ||
*/ | ||
|
||
/* | ||
|
@@ -74,7 +74,11 @@ | |
- Arduino Mega: (D5, D7, D10, D50, D52, D53) | ||
*/ | ||
|
||
#include <Servo.h> | ||
#ifndef ARDUINO_ARCH_ESP32 | ||
// NOTE: ESP32 SKD does not provide an implementation for class Servo | ||
// -> requires a skeleton implementation for Servo in Boards.h to be able to compile | ||
#include <Servo.h> | ||
#endif | ||
#include <Wire.h> | ||
#include <Firmata.h> | ||
|
||
|
@@ -235,8 +239,10 @@ void detachServo(byte pin) | |
} else if (servoCount > 0) { | ||
// keep track of detached servos because we want to reuse their indexes | ||
// before incrementing the count of attached servos | ||
detachedServoCount++; | ||
detachedServos[detachedServoCount - 1] = servoPinMap[pin]; | ||
if (detachedServoCount < MAX_SERVOS) { | ||
detachedServos[detachedServoCount] = servoPinMap[pin]; | ||
detachedServoCount++; | ||
} | ||
} | ||
|
||
servoPinMap[pin] = 255; | ||
|
@@ -370,7 +376,7 @@ void setPinModeCallback(byte pin, int mode) | |
reportAnalogCallback(PIN_TO_ANALOG(pin), mode == PIN_MODE_ANALOG ? 1 : 0); // turn on/off reporting | ||
} | ||
if (IS_PIN_DIGITAL(pin)) { | ||
if (mode == INPUT || mode == PIN_MODE_PULLUP) { | ||
if (mode == PIN_MODE_INPUT || mode == PIN_MODE_PULLUP) { | ||
portConfigInputs[pin / 8] |= (1 << (pin & 7)); | ||
} else { | ||
portConfigInputs[pin / 8] &= ~(1 << (pin & 7)); | ||
|
@@ -390,14 +396,14 @@ void setPinModeCallback(byte pin, int mode) | |
Firmata.setPinMode(pin, PIN_MODE_ANALOG); | ||
} | ||
break; | ||
case INPUT: | ||
case PIN_MODE_INPUT: | ||
if (IS_PIN_DIGITAL(pin)) { | ||
pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver | ||
#if ARDUINO <= 100 | ||
// deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6 | ||
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups | ||
#endif | ||
Firmata.setPinMode(pin, INPUT); | ||
Firmata.setPinMode(pin, PIN_MODE_INPUT); | ||
} | ||
break; | ||
case PIN_MODE_PULLUP: | ||
|
@@ -407,14 +413,14 @@ void setPinModeCallback(byte pin, int mode) | |
Firmata.setPinState(pin, 1); | ||
} | ||
break; | ||
case OUTPUT: | ||
case PIN_MODE_OUTPUT: | ||
if (IS_PIN_DIGITAL(pin)) { | ||
if (Firmata.getPinMode(pin) == PIN_MODE_PWM) { | ||
// Disable PWM if pin mode was previously set to PWM. | ||
digitalWrite(PIN_TO_DIGITAL(pin), LOW); | ||
} | ||
pinMode(PIN_TO_DIGITAL(pin), OUTPUT); | ||
Firmata.setPinMode(pin, OUTPUT); | ||
Firmata.setPinMode(pin, PIN_MODE_OUTPUT); | ||
} | ||
break; | ||
case PIN_MODE_PWM: | ||
|
@@ -461,7 +467,7 @@ void setPinModeCallback(byte pin, int mode) | |
void setPinValueCallback(byte pin, int value) | ||
{ | ||
if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) { | ||
if (Firmata.getPinMode(pin) == OUTPUT) { | ||
if (Firmata.getPinMode(pin) == PIN_MODE_OUTPUT) { | ||
Firmata.setPinState(pin, value); | ||
digitalWrite(PIN_TO_DIGITAL(pin), value); | ||
} | ||
|
@@ -498,11 +504,11 @@ void digitalWriteCallback(byte port, int value) | |
// do not disturb non-digital pins (eg, Rx & Tx) | ||
if (IS_PIN_DIGITAL(pin)) { | ||
// do not touch pins in PWM, ANALOG, SERVO or other modes | ||
if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) { | ||
if (Firmata.getPinMode(pin) == PIN_MODE_OUTPUT || Firmata.getPinMode(pin) == PIN_MODE_INPUT) { | ||
pinValue = ((byte)value & mask) ? 1 : 0; | ||
if (Firmata.getPinMode(pin) == OUTPUT) { | ||
if (Firmata.getPinMode(pin) == PIN_MODE_OUTPUT) { | ||
pinWriteMask |= mask; | ||
} else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) { | ||
} else if (Firmata.getPinMode(pin) == PIN_MODE_INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) { | ||
// only handle INPUT here for backwards compatibility | ||
#if ARDUINO > 100 | ||
pinMode(pin, INPUT_PULLUP); | ||
|
@@ -725,22 +731,26 @@ void sysexCallback(byte command, byte argc, byte *argv) | |
Firmata.write(CAPABILITY_RESPONSE); | ||
for (byte pin = 0; pin < TOTAL_PINS; pin++) { | ||
if (IS_PIN_DIGITAL(pin)) { | ||
Firmata.write((byte)INPUT); | ||
Firmata.write((byte)PIN_MODE_INPUT); | ||
Firmata.write(1); | ||
Firmata.write((byte)PIN_MODE_PULLUP); | ||
Firmata.write(1); | ||
Firmata.write((byte)OUTPUT); | ||
Firmata.write((byte)PIN_MODE_OUTPUT); | ||
Firmata.write(1); | ||
} | ||
if (IS_PIN_ANALOG(pin)) { | ||
Firmata.write(PIN_MODE_ANALOG); | ||
#ifdef DEFAULT_ANALOG_RESOLUTION | ||
Firmata.write(DEFAULT_ANALOG_RESOLUTION); | ||
#else | ||
Firmata.write(10); // 10 = 10-bit resolution | ||
#endif | ||
} | ||
if (IS_PIN_PWM(pin)) { | ||
Firmata.write(PIN_MODE_PWM); | ||
Firmata.write(DEFAULT_PWM_RESOLUTION); | ||
} | ||
if (IS_PIN_DIGITAL(pin)) { | ||
if (IS_PIN_SERVO(pin)) { | ||
Firmata.write(PIN_MODE_SERVO); | ||
Firmata.write(14); | ||
} | ||
|
@@ -820,7 +830,7 @@ void systemResetCallback() | |
setPinModeCallback(i, PIN_MODE_ANALOG); | ||
} else if (IS_PIN_DIGITAL(i)) { | ||
// sets the output to 0, configures portConfigInputs | ||
setPinModeCallback(i, OUTPUT); | ||
setPinModeCallback(i, PIN_MODE_OUTPUT); | ||
} | ||
|
||
servoPinMap[i] = 255; | ||
|
@@ -871,6 +881,7 @@ void printWifiStatus() { | |
DEBUG_PRINT( "WiFi connection failed. Status value: " ); | ||
DEBUG_PRINTLN( WiFi.status() ); | ||
} | ||
#ifdef SERIAL_DEBUG | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this doing for us? How does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SERIAL_DEBUG can be found in StandardFirmataWifi.ino:90. If not enabled with ESP32 SDK (default) the compiler will raise a warning or an error (depending on the compiler settings) because of the unused local variables like "rssi" in line 898, caused by defining DEBUG_PRINT to nothing (see utility/firmataDebug.h). |
||
else | ||
{ | ||
// print the SSID of the network you're attached to: | ||
|
@@ -888,6 +899,7 @@ void printWifiStatus() { | |
DEBUG_PRINT( rssi ); | ||
DEBUG_PRINTLN( " dBm" ); | ||
} | ||
#endif | ||
} | ||
|
||
/* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ | |
are compatible with the Arduino WiFi library. | ||
|
||
Copyright (C) 2015-2016 Jesse Frush. All rights reserved. | ||
Copyright (C) 2016 Jens B. All rights reserved. | ||
Copyright (C) 2016 Jens B. All rights reserved. | ||
|
||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
|
@@ -15,7 +15,7 @@ | |
|
||
See file LICENSE.txt for further informations on licensing terms. | ||
|
||
Last updated April 23rd, 2016 | ||
Last updated December 17th, 2023 | ||
*/ | ||
|
||
#ifndef WIFI_STREAM_H | ||
|
@@ -69,7 +69,7 @@ class WiFiStream : public Stream | |
* network configuration | ||
******************************************************************************/ | ||
|
||
#ifndef ESP8266 | ||
#if (!ESP8266) && (!ARDUINO_ARCH_ESP32) | ||
/** | ||
* configure a static local IP address without defining the local network | ||
* DHCP will be used as long as local IP address is not defined | ||
|
@@ -90,7 +90,7 @@ class WiFiStream : public Stream | |
_local_ip = local_ip; | ||
_subnet = subnet; | ||
_gateway = gateway; | ||
#ifndef ESP8266 | ||
#if (!ESP8266) && (!ARDUINO_ARCH_ESP32) | ||
WiFi.config( local_ip, IPAddress(0, 0, 0, 0), gateway, subnet ); | ||
#else | ||
WiFi.config( local_ip, gateway, subnet ); | ||
|
@@ -135,6 +135,14 @@ class WiFiStream : public Stream | |
{ | ||
return _client.status(); | ||
} | ||
#elif ARDUINO_ARCH_ESP32 | ||
/** | ||
* check if TCP connection is established | ||
*/ | ||
inline uint8_t connected() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are you creating an ESP32 specific API? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The ESP32 SDK does not provide the same functionality as the ESP8266 SDK. For some use cases it is still relevant to know if the stream is connected, as this is not the same as checking the WiFi status. One alternative would be to mimic the ESP8266 implementation and create a status value from the bool provided by the ESP32 SDK. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that's the way to go, especially since there is precedent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
You refer to the alternative I mentioned (to use the previous interface)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, see latest commit. Also added an enum for the possible return values of method status() as the ESP32 SDK does not define constants like the ESP8266 SDK does. |
||
{ | ||
return _client.connected(); | ||
} | ||
#endif | ||
|
||
/** | ||
|
@@ -157,10 +165,10 @@ class WiFiStream : public Stream | |
|
||
WiFi.begin(ssid); | ||
int result = WiFi.status(); | ||
return WiFi.status(); | ||
return result; | ||
} | ||
|
||
#ifndef ESP8266 | ||
#if (!ESP8266) && (!ARDUINO_ARCH_ESP32) | ||
/** | ||
* initialize WiFi with WEP security and initiate client connection | ||
* if WiFi connection is already established | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not the appropriate place to define a class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe. I dont' want this class at all. The source comments give the impression that the Firmata application can do without servos, but than the examples do not build. Adding a new Servo.h to the library itself is also not a good idea because it will create conflicts.
So where put it? Into each example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the example, is it not possible to include ESP32Servo.h?
In theory, you could use the same switch as you are using elsewhere (i.e.
ARDUINO_ARCH_ESP32
).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I already considered using ESP32Servo.h. On first glance it should be compatible, but I did not try so far and I do not have the hardware to verify.
Problem I see here: it's an extra library that needs to be installed separately. So most users will choose the Firmata example, build and get a fail. Only some will read the docs and add the library first. It would be preferable to have the example work out of the box without this extra step and make it still an option. To do this the Servo.h include should be disabled and that can be done with the ARDUINO_ARCH_ESP32 define in the Firmata examples. The result could look like this:
_
#ifdef ARDUINO_ARCH_ESP32
// comment in if ESP32Servo library is installed and servos are required
//#include <ESP32Servo.h>
#else
#include <Servo.h>
#endif
_
What remains to do is to find a solution for the example code that depends on Servo.h. I know this is not ConfigurableFirmata, but previously I had to remove the servo code manually from the INO to make it work without (especially to save codespace for other purposes on small MCUs like the Atmega 328P). Here I see 2 options:
advantage: compact binary
disadvantage: ugly because several code blocks must be taken out
disadvantage: less compact binary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is already a precedent for this behavior, because the regular sample requires the standard Servo library to be installed.
Please remove the class definition and proceed with the following:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, see latest commit. I considered using a preprocessor check "#if __has_include("ESP32Servo.h)" to create a more descriptive error message if the library was not added, but this check is not a C standard and may cause problems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jnsbyr You can add a library dependency by adding a
depends
line tolibrary.properties
, as done here: https://github.com/firmata/ConfigurableFirmata/blob/master/library.properties Then the library manager should automatically grab the dependency.