Skip to content

Commit fbd7667

Browse files
Merge pull request #292 from firmata/wifi-client
Add TCP client and ability to choose between TCP client and Server
2 parents 86a8273 + 562e060 commit fbd7667

File tree

5 files changed

+472
-334
lines changed

5 files changed

+472
-334
lines changed

examples/StandardFirmataWiFi/StandardFirmataWiFi.ino

Lines changed: 104 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,21 @@
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
@@ -46,13 +46,13 @@
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
@@ -87,8 +87,7 @@
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

@@ -110,7 +109,7 @@
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);
130129
IPAddress 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 */
137136
int 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+
*/
828855
void 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

Comments
 (0)