Skip to content

Commit

Permalink
[WiFi] added support for ESP32 architecture and XIAO ESP32C2 board
Browse files Browse the repository at this point in the history
- support for ESP32 architecture with WiFi interface (WiFiStream, Firmata.h, StandardFirmataWiFi)
- support for Seed Studio XIAO ESP32C2 board (Board.h)
- support for Firmata applications without Servo.h (Boards.h, StandardFirmataWiFi)
  • Loading branch information
jnsbyr committed Dec 18, 2023
1 parent 53bb550 commit a3fe862
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 31 deletions.
37 changes: 35 additions & 2 deletions Boards.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Boards.h - Hardware Abstraction Layer for Firmata library
Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
Copyright (C) 2009-2017 Jeff Hoefs. All rights reserved.
Copyright (C) 2023 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
Expand All @@ -10,7 +11,7 @@
See file LICENSE.txt for further informations on licensing terms.
Last updated April 15th, 2018
Last updated December 17th, 2023
*/

#ifndef Firmata_Boards_h
Expand All @@ -29,7 +30,16 @@
// compile, but without support for any Servos. Hopefully that's what the
// user intended by not including Servo.h
#ifndef MAX_SERVOS
#define MAX_SERVOS 0
#define MAX_SERVOS 0
class Servo
{
public:
uint8_t attach(int pin) { return 0; };
uint8_t attach(int pin, int min, int max) { return 0; };
void detach() {};
void write(int value) {};
bool attached() { return false; };
};
#endif

/*
Expand Down Expand Up @@ -1021,6 +1031,29 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define PIN_TO_SERVO(p) (p)
#define DEFAULT_PWM_RESOLUTION 10

// XIAO ESP32C2
// note: Firmata pin numbering schema is by ESP32 GPIO -> IS_XXX checks GPIO number
#elif defined(ARDUINO_XIAO_ESP32C3)
#define TOTAL_ANALOG_PINS (A2 + 1) // (max GPIOx + 1), there are 4 physical analog pins but only 3 are supported by ESP32 SDK 2.0.14 via ADC1
#define TOTAL_PINS NUM_DIGITAL_PINS // (max GPIOx + 1), there are 11 physical pins
#define PIN_SERIAL_RX RX
#define PIN_SERIAL_TX TX
#define IS_PIN_DIGITAL(p) (((p) >= D0 && (p) <= D10) || (p) == D6 || (p) == D7)
#define IS_PIN_ANALOG(p) ((p) >= A0 && (p) <= A2)
#define IS_PIN_PWM(p) 0
#define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && MAX_SERVOS > 0)
#define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL)
#define IS_PIN_SPI(p) ((p) == SS || (p) == MOSI || (p) == MISO || (p) == SCK)
#define IS_PIN_INTERRUPT(p) (digitalPinToInterrupt(p) > NOT_AN_INTERRUPT)
#define IS_PIN_SERIAL(p) ((p) == PIN_SERIAL_RX || (p) == PIN_SERIAL_TX)
#define PIN_TO_DIGITAL(p) ((p) < 6? D0 + (p) : ((p) < 8? D6 + 6 - (p) : (p))) // Dx to GPIOy
#define PIN_TO_ANALOG(p) (p) // FIRMATAx to GPIOy
#define PIN_TO_PWM(p) 127 // @TODO ESP32 SDK does not support analogWrite()
#define PIN_TO_SERVO(p) 127 // @TODO ESP32 SDK does not support servos

#define DEFAULT_PWM_RESOLUTION 8 // see esp32-hal-led.c, analog_resolution
#define DEFAULT_ANALOG_RESOLUTION 12 // see esp32-hal-adc.h, analogSetWidth()

// STM32 based boards
#elif defined(ARDUINO_ARCH_STM32)
#define TOTAL_ANALOG_PINS NUM_ANALOG_INPUTS
Expand Down
6 changes: 4 additions & 2 deletions Firmata.h
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.
Expand Down Expand Up @@ -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
#define PWM 0x03 // same as PIN_MODE_PWM
#define SERVO 0x04 // same as PIN_MODE_SERVO
#define SHIFT 0x05 // same as PIN_MODE_SHIFT
Expand Down
2 changes: 1 addition & 1 deletion FirmataConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace firmata {
*/
static const int FIRMWARE_MAJOR_VERSION = 2;
static const int FIRMWARE_MINOR_VERSION = 5;
static const int FIRMWARE_BUGFIX_VERSION = 7;
static const int FIRMWARE_BUGFIX_VERSION = 10;

/* Version numbers for the protocol. The protocol is still changing, so these
* version numbers are important.
Expand Down
46 changes: 29 additions & 17 deletions examples/StandardFirmataWiFi/StandardFirmataWiFi.ino
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
See file LICENSE.txt for further informations on licensing terms.
Last updated August 17th, 2017
Last updated December 17th, 2023
*/

/*
Expand Down Expand Up @@ -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>

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -871,6 +881,7 @@ void printWifiStatus() {
DEBUG_PRINT( "WiFi connection failed. Status value: " );
DEBUG_PRINTLN( WiFi.status() );
}
#ifdef SERIAL_DEBUG
else
{
// print the SSID of the network you're attached to:
Expand All @@ -888,6 +899,7 @@ void printWifiStatus() {
DEBUG_PRINT( rssi );
DEBUG_PRINTLN( " dBm" );
}
#endif
}

/*
Expand Down
29 changes: 27 additions & 2 deletions examples/StandardFirmataWiFi/wifiConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
*============================================================================*/

// STEP 1 [REQUIRED]
// Uncomment / comment the appropriate set of includes for your hardware (OPTION A, B or C)
// Arduino MKR1000 or ESP8266 are enabled by default if compiling for either of those boards.
// Uncomment / comment the appropriate set of includes for your hardware (OPTION A ... F)
// Arduino MKR1000, ESP8266 and ESP32 are enabled by default if compiling for either of those boards.

/*
* OPTION A: Configure for Arduino MKR1000 or Arduino WiFi Shield 101
Expand Down Expand Up @@ -137,6 +137,31 @@
#endif
#endif

/*
* OPTION F: Configure for ESP32
*
* This will configure StandardFirmataWiFi to use the ESP8266WiFi library for boards
* with an ESP32 chip.
*
* The appropriate libraries are included automatically when compiling for the ESP32 so
* continue on to STEP 2.
*/

#if defined(ARDUINO_ARCH_ESP32)
// automatically include if compiling for ESP32
#define ESP32_WIFI
#endif
#ifdef ESP32_WIFI
#include <WiFi.h>
#include "utility/WiFiClientStream.h"
#include "utility/WiFiServerStream.h"
#ifdef WIFI_LIB_INCLUDED
#define MULTIPLE_WIFI_LIB_INCLUDES
#else
#define WIFI_LIB_INCLUDED
#endif
#endif

//------------------------------
// TODO
//------------------------------
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=Firmata
version=2.5.9
version=2.5.10
author=Firmata Developers
maintainer=Firmata team
sentence=Enables the communication with computer apps using a standard serial protocol. For all Arduino/Genuino boards.
Expand Down
20 changes: 14 additions & 6 deletions utility/WiFiStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 );
Expand Down Expand Up @@ -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()
{
return _client.connected();
}
#endif

/**
Expand All @@ -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
Expand Down

0 comments on commit a3fe862

Please sign in to comment.