2222
2323 See file LICENSE.txt for further informations on licensing terms.
2424
25- Last updated by Jeff Hoefs: April 10th , 2016
25+ Last updated by Jeff Hoefs: April 24th , 2016
2626*/
2727
2828/*
2929 README
3030
31- StandardFirmataWiFi is a WiFi server application. You will need a Firmata client library with
32- a network transport in order to establish a connection with StandardFirmataWiFi .
31+ StandardFirmataWiFi enables the use of Firmata over a TCP connection. It can be configured as
32+ either a TCP server or TCP client .
3333
3434 To use StandardFirmataWiFi you will need to have one of the following
3535 boards or shields:
3636
3737 - Arduino WiFi Shield (or clone)
3838 - Arduino WiFi Shield 101
39- - Arduino MKR1000 board (built-in WiFi 101)
39+ - Arduino MKR1000 board
4040 - ESP8266 WiFi board compatible with ESP8266 Arduino core
4141
4242 Follow the instructions in the wifiConfig.h file (wifiConfig.h tab in Arduino IDE) to
4646 - WiFi Shield 101 requires version 0.7.0 or higher of the WiFi101 library (available in Arduino
4747 1.6.8 or higher, or update the library via the Arduino Library Manager or clone from source:
4848 https://github.com/arduino-libraries/WiFi101)
49- - ESP8266 requires the Arduino ESP8266 core which can be obtained here:
49+ - ESP8266 requires the Arduino ESP8266 core v2.1.0 or higher which can be obtained here:
5050 https://github.com/esp8266/Arduino
5151
52- In order to use the WiFi Shield 101 with Firmata you will need a board with at least
53- 35k of Flash memory. This means you cannot use the WiFi Shield 101 with an Arduino Uno
54- or any other ATmega328p-based microcontroller or with an Arduino Leonardo or other
55- ATmega32u4-based microcontroller. Some boards that will work are:
52+ In order to use the WiFi Shield 101 with Firmata you will need a board with at least 35k of Flash
53+ memory. This means you cannot use the WiFi Shield 101 with an Arduino Uno or any other
54+ ATmega328p-based microcontroller or with an Arduino Leonardo or other ATmega32u4-based
55+ microcontroller. Some boards that will work are:
5656
5757 - Arduino Zero
5858 - Arduino Due
8787
8888/*
8989 * Uncomment the following include to enable interfacing with Serial devices via hardware or
90- * software serial. Note that if enabled, this sketch will likely consume too much memory to run on
91- * an Arduino Uno or Leonardo or other ATmega328p-based or ATmega32u4-based boards.
90+ * software serial.
9291 */
9392// #include "utility/SerialFirmata.h"
9493
110109// the minimum interval for sampling analog input
111110#define MINIMUM_SAMPLING_INTERVAL 1
112111
113- #define WIFI_MAX_CONN_ATTEMPTS 3
112+ #define MAX_CONN_ATTEMPTS 20 // [500 ms] -> 10 s
114113
115114/* ==============================================================================
116115 * GLOBAL VARIABLES
@@ -130,8 +129,8 @@ IPAddress subnet(SUBNET_MASK);
130129IPAddress gateway (GATEWAY_IP_ADDRESS);
131130#endif
132131
133- int wifiConnectionAttemptCounter = 0 ;
134- int wifiStatus = WL_IDLE_STATUS ;
132+ int connectionAttempts = 0 ;
133+ bool streamConnected = false ;
135134
136135/* analog inputs */
137136int analogInputsToReport = 0 ; // bitwise array to store pin reporting
@@ -308,6 +307,12 @@ void checkDigitalInputs(void)
308307 if (TOTAL_PORTS > 15 && reportPINs[15 ]) outputPort (15 , readPort (15 , portConfigInputs[15 ]), false );
309308}
310309
310+ // -----------------------------------------------------------------------------
311+ // function forward declarations for xtensa compiler (ESP8266)
312+ void enableI2CPins ();
313+ void disableI2CPins ();
314+ void reportAnalogCallback (byte analogPin, int value);
315+
311316// -----------------------------------------------------------------------------
312317/* sets the pin mode to the correct state and sets the relevant bits in the
313318 * two bit-arrays that track Digital I/O and PWM status
@@ -825,53 +830,85 @@ void systemResetCallback()
825830 isResetting = false ;
826831}
827832
833+ /*
834+ * Called when a TCP connection is either connected or disconnected.
835+ * TODO:
836+ * - report connected or reconnected state to host (to be added to protocol)
837+ * - report current state to host (to be added to protocol)
838+ */
839+ void hostConnectionCallback (byte state)
840+ {
841+ switch (state) {
842+ case HOST_CONNECTION_CONNECTED:
843+ DEBUG_PRINTLN ( " TCP connection established" );
844+ break ;
845+ case HOST_CONNECTION_DISCONNECTED:
846+ DEBUG_PRINTLN ( " TCP connection disconnected" );
847+ break ;
848+ }
849+ }
850+
851+ /*
852+ * Print the status of the WiFi connection. This is the connection to the access point rather
853+ * than the TCP connection.
854+ */
828855void printWifiStatus () {
829- #if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
830856 if ( WiFi.status () != WL_CONNECTED )
831857 {
832858 DEBUG_PRINT ( " WiFi connection failed. Status value: " );
833859 DEBUG_PRINTLN ( WiFi.status () );
834860 }
835861 else
836- #endif // defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
837862 {
838863 // print the SSID of the network you're attached to:
839864 DEBUG_PRINT ( " SSID: " );
840-
841- #if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
842865 DEBUG_PRINTLN ( WiFi.SSID () );
843- #endif // defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
844866
845867 // print your WiFi shield's IP address:
846868 DEBUG_PRINT ( " IP Address: " );
847-
848- #if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
849869 IPAddress ip = WiFi.localIP ();
850870 DEBUG_PRINTLN ( ip );
851- #endif // defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
852871
853872 // print the received signal strength:
854873 DEBUG_PRINT ( " signal strength (RSSI): " );
855-
856- #if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
857874 long rssi = WiFi.RSSI ();
858875 DEBUG_PRINT ( rssi );
859- #endif // defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
860-
861876 DEBUG_PRINTLN ( " dBm" );
862877 }
863878}
864879
865- void setup ()
880+ /*
881+ * StandardFirmataWiFi communicates with WiFi shields over SPI. Therefore all
882+ * SPI pins must be set to IGNORE. Otherwise Firmata would break SPI communication.
883+ * Additional pins may also need to be ignored depending on the particular board or
884+ * shield in use.
885+ */
886+ void ignorePins ()
866887{
867- /*
868- * WIFI SETUP
869- */
870- DEBUG_BEGIN (9600 );
888+ #ifdef IS_IGNORE_PIN
889+ for (byte i = 0 ; i < TOTAL_PINS; i++) {
890+ if (IS_IGNORE_PIN (i)) {
891+ Firmata.setPinMode (i, PIN_MODE_IGNORE);
892+ }
893+ }
894+ #endif
871895
872- /*
873- * This statement will clarify how a connection is being made
874- */
896+ // Set up controls for the Arduino WiFi Shield SS for the SD Card
897+ #ifdef ARDUINO_WIFI_SHIELD
898+ // Arduino WiFi Shield has SD SS wired to D4
899+ pinMode (PIN_TO_DIGITAL (4 ), OUTPUT); // switch off SD card bypassing Firmata
900+ digitalWrite (PIN_TO_DIGITAL (4 ), HIGH); // SS is active low;
901+
902+ #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
903+ pinMode (PIN_TO_DIGITAL (53 ), OUTPUT); // configure hardware SS as output on MEGA
904+ #endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
905+
906+ #endif // ARDUINO_WIFI_SHIELD
907+ }
908+
909+ void initTransport ()
910+ {
911+ // This statement will clarify how a connection is being made
875912 DEBUG_PRINT ( " StandardFirmataWiFi will attempt a WiFi connection " );
876913#if defined(WIFI_101)
877914 DEBUG_PRINTLN ( " using the WiFi 101 library." );
@@ -884,13 +921,11 @@ void setup()
884921 // else should never happen here as error-checking in wifiConfig.h will catch this
885922#endif // defined(WIFI_101)
886923
887- /*
888- * Configure WiFi IP Address
889- */
924+ // Configure WiFi IP Address
890925#ifdef STATIC_IP_ADDRESS
891926 DEBUG_PRINT ( " Using static IP: " );
892927 DEBUG_PRINTLN ( local_ip );
893- #ifdef ESP8266_WIFI
928+ #if defined( ESP8266_WIFI) || (defined(SUBNET_MASK) && defined(GATEWAY_IP_ADDRESS))
894929 stream.config ( local_ip , gateway, subnet );
895930#else
896931 // you can also provide a static IP in the begin() functions, but this simplifies
@@ -901,45 +936,35 @@ void setup()
901936 DEBUG_PRINTLN ( " IP will be requested from DHCP ..." );
902937#endif
903938
904- /*
905- * Configure WiFi security
906- */
907- #if defined(WIFI_WEP_SECURITY)
908- while (wifiStatus != WL_CONNECTED) {
909- DEBUG_PRINT ( " Attempting to connect to WEP SSID: " );
910- DEBUG_PRINTLN (ssid);
911- wifiStatus = stream.begin ( ssid, wep_index, wep_key, SERVER_PORT );
912- delay (5000 ); // TODO - determine minimum delay
913- if (++wifiConnectionAttemptCounter > WIFI_MAX_CONN_ATTEMPTS) break ;
914- }
939+ stream.attach (hostConnectionCallback);
915940
941+ // Configure WiFi security and initiate WiFi connection
942+ #if defined(WIFI_WEP_SECURITY)
943+ DEBUG_PRINT ( " Attempting to connect to WEP SSID: " );
944+ DEBUG_PRINTLN (ssid);
945+ stream.begin (ssid, wep_index, wep_key);
916946#elif defined(WIFI_WPA_SECURITY)
917- while (wifiStatus != WL_CONNECTED) {
918- DEBUG_PRINT ( " Attempting to connect to WPA SSID: " );
919- DEBUG_PRINTLN (ssid);
920- wifiStatus = stream.begin (ssid, wpa_passphrase, SERVER_PORT);
921- delay (5000 ); // TODO - determine minimum delay
922- if (++wifiConnectionAttemptCounter > WIFI_MAX_CONN_ATTEMPTS) break ;
923- }
924-
947+ DEBUG_PRINT ( " Attempting to connect to WPA SSID: " );
948+ DEBUG_PRINTLN (ssid);
949+ stream.begin (ssid, wpa_passphrase);
925950#else // OPEN network
926- while (wifiStatus != WL_CONNECTED) {
927- DEBUG_PRINTLN ( " Attempting to connect to open SSID: " );
928- DEBUG_PRINTLN (ssid);
929- wifiStatus = stream.begin (ssid, SERVER_PORT);
930- delay (5000 ); // TODO - determine minimum delay
931- if (++wifiConnectionAttemptCounter > WIFI_MAX_CONN_ATTEMPTS) break ;
932- }
951+ DEBUG_PRINTLN ( " Attempting to connect to open SSID: " );
952+ DEBUG_PRINTLN (ssid);
953+ stream.begin (ssid);
933954#endif // defined(WIFI_WEP_SECURITY)
934-
935955 DEBUG_PRINTLN ( " WiFi setup done" );
956+
957+ // Wait for connection to access point to be established.
958+ while (WiFi.status () != WL_CONNECTED && ++connectionAttempts <= MAX_CONN_ATTEMPTS) {
959+ delay (500 );
960+ DEBUG_PRINT (" ." );
961+ }
936962 printWifiStatus ();
963+ }
937964
938- /*
939- * FIRMATA SETUP
940- */
965+ void initFirmata ()
966+ {
941967 Firmata.setFirmwareVersion (FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
942-
943968 Firmata.attach (ANALOG_MESSAGE, analogWriteCallback);
944969 Firmata.attach (DIGITAL_MESSAGE, digitalWriteCallback);
945970 Firmata.attach (REPORT_ANALOG, reportAnalogCallback);
@@ -949,47 +974,20 @@ void setup()
949974 Firmata.attach (START_SYSEX, sysexCallback);
950975 Firmata.attach (SYSTEM_RESET, systemResetCallback);
951976
952- // StandardFirmataWiFi communicates with WiFi shields over SPI. Therefore all
953- // SPI pins must be set to IGNORE. Otherwise Firmata would break SPI communication.
954- // Additional pins may also need to be ignored depending on the particular board or
955- // shield in use.
977+ ignorePins ();
956978
957- for (byte i = 0 ; i < TOTAL_PINS; i++) {
958- #if defined(ARDUINO_WIFI_SHIELD)
959- if (IS_IGNORE_WIFI_SHIELD (i)
960- #if defined(__AVR_ATmega32U4__)
961- || 24 == i // On Leonardo, pin 24 maps to D4 and pin 28 maps to D10
962- || 28 == i
963- #endif // defined(__AVR_ATmega32U4__)
964- ) {
965- // don't ignore pins when using Wi-Fi 101 library with the MKR1000
966- #elif defined (WIFI_101) && !defined(ARDUINO_SAMD_MKR1000)
967- if (IS_IGNORE_WIFI101_SHIELD (i)) {
968- #elif defined (HUZZAH_WIFI)
969- // TODO
970- if (false ) {
971- #else
972- if (false ) {
973- #endif
974- Firmata.setPinMode (i, PIN_MODE_IGNORE);
975- }
976- }
977-
978- // Set up controls for the Arduino WiFi Shield SS for the SD Card
979- #ifdef ARDUINO_WIFI_SHIELD
980- // Arduino WiFi, Arduino WiFi Shield and Arduino Yun all have SD SS wired to D4
981- pinMode (PIN_TO_DIGITAL (4 ), OUTPUT); // switch off SD card bypassing Firmata
982- digitalWrite (PIN_TO_DIGITAL (4 ), HIGH); // SS is active low;
979+ // Initialize Firmata to use the WiFi stream object as the transport.
980+ Firmata.begin (stream);
981+ systemResetCallback (); // reset to default config
982+ }
983983
984- # if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__ )
985- pinMode ( PIN_TO_DIGITAL ( 53 ), OUTPUT); // configure hardware SS as output on MEGA
986- # endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
984+ void setup ( )
985+ {
986+ DEBUG_BEGIN ( 9600 );
987987
988- # endif // ARDUINO_WIFI_SHIELD
988+ initTransport ();
989989
990- // start up Network Firmata:
991- Firmata.begin (stream);
992- systemResetCallback (); // reset to default config
990+ initFirmata ();
993991}
994992
995993/* ==============================================================================
0 commit comments