22
22
23
23
See file LICENSE.txt for further informations on licensing terms.
24
24
25
- Last updated by Jeff Hoefs: April 10th , 2016
25
+ Last updated by Jeff Hoefs: April 24th , 2016
26
26
*/
27
27
28
28
/*
29
29
README
30
30
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 .
33
33
34
34
To use StandardFirmataWiFi you will need to have one of the following
35
35
boards or shields:
36
36
37
37
- Arduino WiFi Shield (or clone)
38
38
- Arduino WiFi Shield 101
39
- - Arduino MKR1000 board (built-in WiFi 101)
39
+ - Arduino MKR1000 board
40
40
- ESP8266 WiFi board compatible with ESP8266 Arduino core
41
41
42
42
Follow the instructions in the wifiConfig.h file (wifiConfig.h tab in Arduino IDE) to
46
46
- WiFi Shield 101 requires version 0.7.0 or higher of the WiFi101 library (available in Arduino
47
47
1.6.8 or higher, or update the library via the Arduino Library Manager or clone from source:
48
48
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:
50
50
https://github.com/esp8266/Arduino
51
51
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:
56
56
57
57
- Arduino Zero
58
58
- Arduino Due
87
87
88
88
/*
89
89
* 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.
92
91
*/
93
92
// #include "utility/SerialFirmata.h"
94
93
110
109
// the minimum interval for sampling analog input
111
110
#define MINIMUM_SAMPLING_INTERVAL 1
112
111
113
- #define WIFI_MAX_CONN_ATTEMPTS 3
112
+ #define MAX_CONN_ATTEMPTS 20 // [500 ms] -> 10 s
114
113
115
114
/* ==============================================================================
116
115
* GLOBAL VARIABLES
@@ -130,8 +129,8 @@ IPAddress subnet(SUBNET_MASK);
130
129
IPAddress gateway (GATEWAY_IP_ADDRESS);
131
130
#endif
132
131
133
- int wifiConnectionAttemptCounter = 0 ;
134
- int wifiStatus = WL_IDLE_STATUS ;
132
+ int connectionAttempts = 0 ;
133
+ bool streamConnected = false ;
135
134
136
135
/* analog inputs */
137
136
int analogInputsToReport = 0 ; // bitwise array to store pin reporting
@@ -308,6 +307,12 @@ void checkDigitalInputs(void)
308
307
if (TOTAL_PORTS > 15 && reportPINs[15 ]) outputPort (15 , readPort (15 , portConfigInputs[15 ]), false );
309
308
}
310
309
310
+ // -----------------------------------------------------------------------------
311
+ // function forward declarations for xtensa compiler (ESP8266)
312
+ void enableI2CPins ();
313
+ void disableI2CPins ();
314
+ void reportAnalogCallback (byte analogPin, int value);
315
+
311
316
// -----------------------------------------------------------------------------
312
317
/* sets the pin mode to the correct state and sets the relevant bits in the
313
318
* two bit-arrays that track Digital I/O and PWM status
@@ -825,53 +830,85 @@ void systemResetCallback()
825
830
isResetting = false ;
826
831
}
827
832
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
+ */
828
855
void printWifiStatus () {
829
- #if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
830
856
if ( WiFi.status () != WL_CONNECTED )
831
857
{
832
858
DEBUG_PRINT ( " WiFi connection failed. Status value: " );
833
859
DEBUG_PRINTLN ( WiFi.status () );
834
860
}
835
861
else
836
- #endif // defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
837
862
{
838
863
// print the SSID of the network you're attached to:
839
864
DEBUG_PRINT ( " SSID: " );
840
-
841
- #if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
842
865
DEBUG_PRINTLN ( WiFi.SSID () );
843
- #endif // defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
844
866
845
867
// print your WiFi shield's IP address:
846
868
DEBUG_PRINT ( " IP Address: " );
847
-
848
- #if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
849
869
IPAddress ip = WiFi.localIP ();
850
870
DEBUG_PRINTLN ( ip );
851
- #endif // defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
852
871
853
872
// print the received signal strength:
854
873
DEBUG_PRINT ( " signal strength (RSSI): " );
855
-
856
- #if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
857
874
long rssi = WiFi.RSSI ();
858
875
DEBUG_PRINT ( rssi );
859
- #endif // defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(ESP8266_WIFI)
860
-
861
876
DEBUG_PRINTLN ( " dBm" );
862
877
}
863
878
}
864
879
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 ()
866
887
{
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
871
895
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
875
912
DEBUG_PRINT ( " StandardFirmataWiFi will attempt a WiFi connection " );
876
913
#if defined(WIFI_101)
877
914
DEBUG_PRINTLN ( " using the WiFi 101 library." );
@@ -884,13 +921,11 @@ void setup()
884
921
// else should never happen here as error-checking in wifiConfig.h will catch this
885
922
#endif // defined(WIFI_101)
886
923
887
- /*
888
- * Configure WiFi IP Address
889
- */
924
+ // Configure WiFi IP Address
890
925
#ifdef STATIC_IP_ADDRESS
891
926
DEBUG_PRINT ( " Using static IP: " );
892
927
DEBUG_PRINTLN ( local_ip );
893
- #ifdef ESP8266_WIFI
928
+ #if defined( ESP8266_WIFI) || (defined(SUBNET_MASK) && defined(GATEWAY_IP_ADDRESS))
894
929
stream.config ( local_ip , gateway, subnet );
895
930
#else
896
931
// you can also provide a static IP in the begin() functions, but this simplifies
@@ -901,45 +936,35 @@ void setup()
901
936
DEBUG_PRINTLN ( " IP will be requested from DHCP ..." );
902
937
#endif
903
938
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);
915
940
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);
916
946
#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);
925
950
#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);
933
954
#endif // defined(WIFI_WEP_SECURITY)
934
-
935
955
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
+ }
936
962
printWifiStatus ();
963
+ }
937
964
938
- /*
939
- * FIRMATA SETUP
940
- */
965
+ void initFirmata ()
966
+ {
941
967
Firmata.setFirmwareVersion (FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
942
-
943
968
Firmata.attach (ANALOG_MESSAGE, analogWriteCallback);
944
969
Firmata.attach (DIGITAL_MESSAGE, digitalWriteCallback);
945
970
Firmata.attach (REPORT_ANALOG, reportAnalogCallback);
@@ -949,47 +974,20 @@ void setup()
949
974
Firmata.attach (START_SYSEX, sysexCallback);
950
975
Firmata.attach (SYSTEM_RESET, systemResetCallback);
951
976
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 ();
956
978
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
+ }
983
983
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 );
987
987
988
- # endif // ARDUINO_WIFI_SHIELD
988
+ initTransport ();
989
989
990
- // start up Network Firmata:
991
- Firmata.begin (stream);
992
- systemResetCallback (); // reset to default config
990
+ initFirmata ();
993
991
}
994
992
995
993
/* ==============================================================================
0 commit comments