diff --git a/examples/ConfigurableFirmata/ConfigurableFirmata.ino b/examples/ConfigurableFirmata/ConfigurableFirmata.ino index e063b53..4df40d7 100644 --- a/examples/ConfigurableFirmata/ConfigurableFirmata.ino +++ b/examples/ConfigurableFirmata/ConfigurableFirmata.ino @@ -25,59 +25,128 @@ Last updated by Jeff Hoefs: January 23rd, 2016 */ +/* + README + + This is an example use of ConfigurableFirmata. The easiest way to create a configuration is to + use http://firmatabuilder.com and select the communication transport and the firmata features + to include and an Arduino sketch (.ino) file will be generated and downloaded automatically. + + To manually configure a sketch, copy this file and follow the instructions in the + ETHERNET CONFIGURATION OPTION (if you want to use Ethernet instead of Serial/USB) and + FIRMATA FEATURE CONFIGURATION sections in this file. +*/ + #include "ConfigurableFirmata.h" +/*============================================================================== + * ETHERNET CONFIGURATION OPTION + * + * By default Firmata uses the Serial-port (over USB) of the Arduino. ConfigurableFirmata may also + * comunicate over ethernet using tcp/ip. To configure this sketch to use Ethernet instead of + * Serial, uncomment the approprate includes for your particular hardware. See STEPS 1 - 5 below. + * If you want to use Serial (over USB) then skip ahead to the FIRMATA FEATURE CONFIGURATION + * section further down in this file. + * + * If you enable Ethernet, you will need a Firmata client library with a network transport that can + * act as a server in order to establish a connection between ConfigurableFirmataEthernet and the + * Firmata host application (your application). + * + * To use ConfigurableFirmata with Ethernet you will need to have one of the following + * boards or shields: + * + * - Arduino Ethernet shield (or clone) + * - Arduino Ethernet board (or clone) + * - Arduino Yun + * + * If you are using an Arduino Ethernet shield you cannot use the following pins on + * the following boards. Firmata will ignore any requests to use these pins: + * + * - Arduino Uno or other ATMega328 boards: (D4, D10, D11, D12, D13) + * - Arduino Mega: (D4, D10, D50, D51, D52, D53) + * - Arduino Leonardo: (D4, D10) + * - Arduino Due: (D4, D10) + * - Arduino Zero: (D4, D10) + * + * If you are using an ArduinoEthernet board, the following pins cannot be used (same as Uno): + * - D4, D10, D11, D12, D13 + *============================================================================*/ + +// STEP 1 [REQUIRED] +// Uncomment / comment the appropriate set of includes for your hardware (OPTION A, B or C) + /* - * by default Firmata uses the Serial-port (over USB) of Arduino. - * ConfigurableFirmata may also comunicate over ethernet using tcp/ip. - * To configure this 'Network Firmata' to use the original WIZ5100-based - * ethernet-shield or Arduino Ethernet uncomment the includes of 'SPI.h' and 'Ethernet.h': + * OPTION A: Configure for Arduino Ethernet board or Arduino Ethernet shield (or clone) + * + * To configure ConfigurableFirmata to use the an Arduino Ethernet Shield or Arduino Ethernet + * Board (both use the same WIZ5100-based Ethernet controller), uncomment the SPI and Ethernet + * includes below. */ - //#include //#include + /* - * To configure 'Network Firmata' to use an ENC28J60 based board include - * 'UIPEthernet.h' (no SPI.h required). The UIPEthernet-library can be downloaded + * OPTION B: Configure for a board or shield using an ENC28J60-based Ethernet controller, + * uncomment out the UIPEthernet include below. + * + * The UIPEthernet-library can be downloaded * from: https://github.com/ntruchsess/arduino_uip */ - //#include + /* - * To execute Network Firmata on Yun uncomment Bridge.h and YunClient.h. - * Do not include Ethernet.h or SPI.h in this case. - * On Yun there's no need to configure local_ip and mac in the sketch - * as this is configured on the linux-side of Yun. + * OPTION C: Configure for Arduino Yun + * + * The Ethernet port on the Arduino Yun board can be used with Firmata in this configuration. + * To execute StandardFirmataEthernet on Yun uncomment the Bridge and YunClient includes below. + * + * NOTE: in order to compile for the Yun you will also need to comment out some of the includes + * and declarations in the FIRMATA FEATURE CONFIGURATION section later in this file. Including all + * features exceeds the RAM and Flash memory of the Yun. Comment out anything you don't need. + * + * On Yun there's no need to configure local_ip and mac address as this is automatically + * configured on the linux-side of Yun. + * + * Establishing a connection with the Yun may take several seconds. */ - //#include //#include #if defined ethernet_h || defined UIPETHERNET_H || defined _YUN_CLIENT_H_ -/*============================================================================== - * Network configuration for Network Firmata - *============================================================================*/ #define NETWORK_FIRMATA -//replace with ip of server you want to connect to, comment out if using 'remote_host' + +// STEP 2 [REQUIRED for all boards and shields] +// replace with IP of the server you want to connect to, comment out if using 'remote_host' #define remote_ip IPAddress(192, 168, 0, 1) -//replace with hostname of server you want to connect to, comment out if using 'remote_ip' -#define remote_host "server.local" -//replace with the port that your server is listening on +// OR replace with hostname of server you want to connect to, comment out if using 'remote_ip' +// #define remote_host "server.local" + +// STEP 3 [REQUIRED unless using Arduino Yun] +// Replace with the port that your server is listening on #define remote_port 3030 -//replace with arduinos ip-address. Comment out if Ethernet-startup should use dhcp. Is ignored on Yun + +// STEP 4 [REQUIRED unless using Arduino Yun OR if not using DHCP] +// Replace with your board or Ethernet shield's IP address +// Comment out if you want to use DHCP #define local_ip IPAddress(192, 168, 0, 6) -//replace with ethernet shield mac. It's mandatory every device is assigned a unique mac. Is ignored on Yun + +// STEP 5 [REQUIRED unless using Arduino Yun] +// replace with Ethernet shield mac. Must be unique for your network const byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x07, 0x02}; #endif -// To configure, save this file to your working directory so you can edit it -// then comment out the include and declaration for any features that you do -// not need below. - -// WARNING: Including all of the following features (especially if also using Ethernet) may exceed -// the Flash and/or RAM of lower memory boards such as the Arduino Uno or Leonardo. +/*============================================================================== + * FIRMATA FEATURE CONFIGURATION + * + * Comment out the include and declaration for any features that you do not need + * below. + * + * WARNING: Including all of the following features (especially if also using + * Ethernet) may exceed the Flash and/or RAM of lower memory boards such as the + * Arduino Uno or Leonardo. + *============================================================================*/ #include DigitalInputFirmata digitalInput; @@ -125,6 +194,9 @@ FirmataScheduler scheduler; // #include // FirmataEncoder encoder; +/*=================================================================================== + * END FEATURE CONFIGURATION - you should not need to change anything below this line + *==================================================================================*/ // dependencies. Do not comment out the following lines #if defined AnalogOutputFirmata_h || defined ServoFirmata_h @@ -169,14 +241,14 @@ EthernetClientStream stream(client, IPAddress(0, 0, 0, 0), IPAddress(0, 0, 0, 0) void systemResetCallback() { - // initialize a defalt state + // initialize a default state // pins with analog capability default to analog input // otherwise, pins default to digital output for (byte i = 0; i < TOTAL_PINS; i++) { if (IS_PIN_ANALOG(i)) { #ifdef AnalogInputFirmata_h - // turns off pullup, configures everything + // turns off pull-up, configures everything Firmata.setPinMode(i, PIN_MODE_ANALOG); #endif } else if (IS_PIN_DIGITAL(i)) { @@ -198,18 +270,25 @@ void systemResetCallback() void setup() { + /* + * ETHERNET SETUP + */ #ifdef NETWORK_FIRMATA #ifdef _YUN_CLIENT_H_ Bridge.begin(); #else #ifdef local_ip - Ethernet.begin((uint8_t *)mac, local_ip); //start ethernet + Ethernet.begin((uint8_t *)mac, local_ip); //start Ethernet #else - Ethernet.begin((uint8_t *)mac); //start ethernet using dhcp + Ethernet.begin((uint8_t *)mac); //start Ethernet using dhcp #endif #endif delay(1000); #endif + + /* + * FIRMATA SETUP + */ Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION); #ifdef FirmataExt_h @@ -258,10 +337,12 @@ void setup() // add Pin 10 and configure pin 53 as output if using a MEGA with Ethernetshield. // No need to ignore pin 10 on MEGA with ENC28J60, as here pin 53 should be connected to SS: #ifdef NETWORK_FIRMATA + + #ifndef _YUN_CLIENT_H_ // ignore SPI and pin 4 that is SS for SD-Card on Ethernet-shield for (byte i = 0; i < TOTAL_PINS; i++) { if (IS_PIN_SPI(i) - || 4 == i // SD-Card on Ethernet-shiedl uses pin 4 for SS + || 4 == i // SD Card on Ethernet shield uses pin 4 for SS || 10 == i // Ethernet-shield uses pin 10 for SS ) { Firmata.setPinMode(i, PIN_MODE_IGNORE); @@ -270,10 +351,11 @@ void setup() // pinMode(PIN_TO_DIGITAL(53), OUTPUT); configure hardware-SS as output on MEGA pinMode(PIN_TO_DIGITAL(4), OUTPUT); // switch off SD-card bypassing Firmata digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low; + #endif -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware SS as output on MEGA -#endif + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware SS as output on MEGA + #endif // start up Network Firmata: Firmata.begin(stream); @@ -298,7 +380,7 @@ void loop() digitalInput.report(); #endif - /* STREAMREAD - processing incoming messagse as soon as possible, while still + /* STREAMREAD - processing incoming message as soon as possible, while still * checking digital inputs. */ while (Firmata.available()) { Firmata.processInput(); diff --git a/examples/ConfigurableFirmataWiFi/ConfigurableFirmataWiFi.ino b/examples/ConfigurableFirmataWiFi/ConfigurableFirmataWiFi.ino new file mode 100644 index 0000000..cff209e --- /dev/null +++ b/examples/ConfigurableFirmataWiFi/ConfigurableFirmataWiFi.ino @@ -0,0 +1,609 @@ +/* + Firmata is a generic protocol for communicating with microcontrollers + from software on a host computer. It is intended to work with + any host computer software package. + + To download a host software package, please clink on the following link + to open the download page in your default browser. + + https://github.com/firmata/ConfigurableFirmata#firmata-client-libraries + + Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved. + Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved. + Copyright (C) 2009 Shigeru Kobayashi. All rights reserved. + Copyright (C) 2013 Norbert Truchsess. All rights reserved. + Copyright (C) 2014 Nicolas Panel. All rights reserved. + Copyright (C) 2015-2016 Jesse Frush. All rights reserved. + Copyright (C) 2009-2016 Jeff Hoefs. 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 + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See file LICENSE.txt for further informations on licensing terms. + + Last updated by Jeff Hoefs: January 23rd, 2016 +*/ + +/* + README + + This is an example use of ConfigurableFirmata with WiFi. The easiest way to create a + configuration is use http://firmatabuilder.com and select the communication transport and the + firmata features to include and an Arduino sketch (.ino) file will be generated and downloaded + automatically. + + To manually configure a sketch, follow the instructions in this file. + + ConfigurableFirmataWiFi is a WiFi server application. You will need a Firmata client library with + a network transport in order to establish a connection with ConfigurableFirmataWiFi. + + To use ConfigurableFirmataWiFi you will need to have one of the following + boards or shields: + + - Arduino WiFi Shield (or clone) + - Arduino WiFi Shield 101 + - Arduino MKR1000 board (built-in WiFi 101) + - Adafruit HUZZAH CC3000 WiFi Shield (support coming soon) + + Follow the instructions in the WIFI CONFIGURATION section below to configure your particular + hardware. + + Dependencies: + - WiFi Shield 101 requires version 0.7.0 or higher of the WiFi101 library (available in Arduino + 1.6.8 or higher, or update the library via the Arduino Library Manager or clone from source: + https://github.com/arduino-libraries/WiFi101) + + In order to use the WiFi Shield 101 with Firmata you will need a board with at least + 35k of Flash memory. This means you cannot use the WiFi Shield 101 with an Arduino Uno + or any other ATmega328p-based microcontroller or with an Arduino Leonardo or other + ATmega32u4-based microcontroller. Some boards that will work are: + + - Arduino Zero + - Arduino Due + - Arduino 101 + - Arduino Mega + + NOTE: If you are using an Arduino WiFi (legacy) shield you cannot use the following pins on + the following boards. Firmata will ignore any requests to use these pins: + + - Arduino Uno or other ATMega328 boards: (D4, D7, D10, D11, D12, D13) + - Arduino Mega: (D4, D7, D10, D50, D51, D52, D53) + - Arduino Due, Zero or Leonardo: (D4, D7, D10) + + If you are using an Arduino WiFi 101 shield you cannot use the following pins on the following + boards: + + - Arduino Due or Zero: (D5, D7, D10) + - Arduino Mega: (D5, D7, D10, D50, D52, D53) +*/ + +#include "ConfigurableFirmata.h" + +/* + * Uncomment the #define SERIAL_DEBUG line below to receive serial output messages relating to your + * connection that may help in the event of connection issues. If defined, some boards may not begin + * executing this sketch until the Serial console is opened. + */ +//#define SERIAL_DEBUG +#include "utility/firmataDebug.h" + +#define WIFI_MAX_CONN_ATTEMPTS 3 + +/*============================================================================== + * WIFI CONFIGURATION + * + * You must configure your particular hardware. Follow the steps below. + * + * Currently ConfigurableFirmataWiFi is configured as a server. An option to + * configure as a client may be added in the future. + *============================================================================*/ + +// STEP 1 [REQUIRED] +// Uncomment / comment the appropriate set of includes for your hardware (OPTION A, B or C) +// Option A is enabled by default. + +/* + * OPTION A: Configure for Arduino WiFi shield + * + * This will configure ConfigurableFirmataWiFi to use the original WiFi library (deprecated) + * provided with the Arduino IDE. It is supported by the Arduino WiFi shield (a discontinued + * product) and is compatible with 802.11 B/G networks. + * + * To configure ConfigurableFirmataWiFi to use the Arduino WiFi shield + * leave the #define below uncommented. + */ +#define ARDUINO_WIFI_SHIELD + +//do not modify these next 4 lines +#ifdef ARDUINO_WIFI_SHIELD +#include "utility/WiFiStream.h" +WiFiStream stream; +#endif + +/* + * OPTION B: Configure for WiFi 101 + * + * This will configure ConfigurableFirmataWiFi to use the WiFi101 library, which works with the + * Arduino WiFi101 shield and devices that have the WiFi101 chip built in (such as the MKR1000). It + * is compatible with 802.11 B/G/N networks. + * + * To enable, uncomment the #define WIFI_101 below and verify the #define values under + * options A and C are commented out. + * + * IMPORTANT: You must have the WiFI 101 library installed. To easily install this library, open + * the library manager via: Arduino IDE Menus: Sketch > Include Library > Manage Libraries > + * filter search for "WiFi101" > Select the result and click 'install' + */ +//#define WIFI_101 + +//do not modify these next 4 lines +#ifdef WIFI_101 +#include "utility/WiFi101Stream.h" +WiFi101Stream stream; +#endif + +/* + * OPTION C: Configure for HUZZAH + * + * HUZZAH is not yet supported, this will be added in a later revision to ConfigurableFirmataWiFi + */ + +//------------------------------ +// TODO +//------------------------------ +//#define HUZZAH_WIFI + + +// STEP 2 [REQUIRED for all boards and shields] +// replace this with your wireless network SSID +char ssid[] = "your_network_name"; + +// STEP 3 [OPTIONAL for all boards and shields] +// If you want to use a static IP (v4) address, uncomment the line below. You can also change the IP. +// If this line is commented out, the WiFi shield will attempt to get an IP from the DHCP server +// #define STATIC_IP_ADDRESS 192,168,1,113 + +// STEP 4 [REQUIRED for all boards and shields] +// define your port number here, you will need this to open a TCP connection to your Arduino +#define SERVER_PORT 3030 + +// STEP 5 [REQUIRED for all boards and shields] +// determine your network security type (OPTION A, B, or C). Option A is the most common, and the default. + + +/* + * OPTION A: WPA / WPA2 + * + * WPA is the most common network security type. A passphrase is required to connect to this type. + * + * To enable, leave #define WIFI_WPA_SECURITY uncommented below, set your wpa_passphrase value + * appropriately, and do not uncomment the #define values under options B and C + */ +#define WIFI_WPA_SECURITY + +#ifdef WIFI_WPA_SECURITY +char wpa_passphrase[] = "your_wpa_passphrase"; +#endif //WIFI_WPA_SECURITY + +/* + * OPTION B: WEP + * + * WEP is a less common (and regarded as less safe) security type. A WEP key and its associated + * index are required to connect to this type. + * + * To enable, Uncomment the #define below, set your wep_index and wep_key values appropriately, and + * verify the #define values under options A and C are commented out. + */ +//#define WIFI_WEP_SECURITY + +#ifdef WIFI_WEP_SECURITY +//The wep_index below is a zero-indexed value. +//Valid indices are [0-3], even if your router/gateway numbers your keys [1-4]. +byte wep_index = 0; +char wep_key[] = "your_wep_key"; +#endif //WIFI_WEP_SECURITY + + +/* + * OPTION C: Open network (no security) + * + * Open networks have no security, can be connected to by any device that knows the ssid, and are + * unsafe. + * + * To enable, uncomment #define WIFI_NO_SECURITY below and verify the #define values + * under options A and B are commented out. + */ +//#define WIFI_NO_SECURITY + +/*============================================================================== + * CONFIGURATION ERROR CHECK (don't change anything here) + *============================================================================*/ + +#if ((defined(ARDUINO_WIFI_SHIELD) && (defined(WIFI_101) || defined(HUZZAH_WIFI))) || (defined(WIFI_101) && defined(HUZZAH_WIFI))) +#error "you may not define more than one wifi device type in wifiConfig.h." +#endif //WIFI device type check + +#if !(defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) || defined(HUZZAH_WIFI)) +#error "you must define a wifi device type in wifiConfig.h." +#endif + +#if ((defined(WIFI_NO_SECURITY) && (defined(WIFI_WEP_SECURITY) || defined(WIFI_WPA_SECURITY))) || (defined(WIFI_WEP_SECURITY) && defined(WIFI_WPA_SECURITY))) +#error "you may not define more than one security type at the same time in wifiConfig.h." +#endif //WIFI_* security define check + +#if !(defined(WIFI_NO_SECURITY) || defined(WIFI_WEP_SECURITY) || defined(WIFI_WPA_SECURITY)) +#error "you must define a wifi security type in wifiConfig.h." +#endif //WIFI_* security define check + +/*============================================================================== + * PIN IGNORE MACROS (don't change anything here) + *============================================================================*/ + +// ignore SPI pins, pin 5 (reset WiFi101 shield), pin 7 (WiFi handshake) and pin 10 (WiFi SS) +// also don't ignore SS pin if it's not pin 10 +// TODO - need to differentiate between Arduino WiFi1 101 Shield and Arduino MKR1000 +#define IS_IGNORE_WIFI101_SHIELD(p) ((p) == 10 || (IS_PIN_SPI(p) && (p) != SS) || (p) == 5 || (p) == 7) + +// ignore SPI pins, pin 4 (SS for SD-Card on WiFi-shield), pin 7 (WiFi handshake) and pin 10 (WiFi SS) +#define IS_IGNORE_WIFI_SHIELD(p) ((IS_PIN_SPI(p) || (p) == 4) || (p) == 7 || (p) == 10) + + +/*============================================================================== + * FIRMATA FEATURE CONFIGURATION + * + * Comment out the include and declaration for any features that you do not need + * below. + * + * WARNING: Including all of the following features (especially if also using + * Ethernet) may exceed the Flash and/or RAM of lower memory boards such as the + * Arduino Uno or Leonardo. + *============================================================================*/ + +#include +DigitalInputFirmata digitalInput; + +#include +DigitalOutputFirmata digitalOutput; + +#include +AnalogInputFirmata analogInput; + +#include +AnalogOutputFirmata analogOutput; + +#include +#include +ServoFirmata servo; +// ServoFirmata depends on AnalogOutputFirmata +#if defined ServoFirmata_h && ! defined AnalogOutputFirmata_h +#error AnalogOutputFirmata must be included to use ServoFirmata +#endif + +#include +#include +I2CFirmata i2c; + +#include +OneWireFirmata oneWire; + +#include +StepperFirmata stepper; + +#include +SerialFirmata serial; + +#include +FirmataExt firmataExt; + +#include +FirmataScheduler scheduler; + +// To add Encoder support you must first install the FirmataEncoder and Encoder libraries: +// https://github.com/firmata/FirmataEncoder +// https://www.pjrc.com/teensy/td_libs_Encoder.html +// #include +// #include +// FirmataEncoder encoder; + +/*=================================================================================== + * END FEATURE CONFIGURATION - you should not need to change anything below this line + *==================================================================================*/ + +// dependencies. Do not comment out the following lines +#if defined AnalogOutputFirmata_h || defined ServoFirmata_h +#include +#endif + +#if defined AnalogInputFirmata_h || defined I2CFirmata_h || defined FirmataEncoder_h +#include +FirmataReporting reporting; +#endif + + +#ifdef STATIC_IP_ADDRESS +IPAddress local_ip(STATIC_IP_ADDRESS); +#endif + +int wifiConnectionAttemptCounter = 0; +int wifiStatus = WL_IDLE_STATUS; + +/*============================================================================== + * FUNCTIONS + *============================================================================*/ + +void systemResetCallback() +{ + // initialize a default state + + // pins with analog capability default to analog input + // otherwise, pins default to digital output + for (byte i = 0; i < TOTAL_PINS; i++) { + if (IS_PIN_ANALOG(i)) { +#ifdef AnalogInputFirmata_h + // turns off pull-up, configures everything + Firmata.setPinMode(i, PIN_MODE_ANALOG); +#endif + } else if (IS_PIN_DIGITAL(i)) { +#ifdef DigitalOutputFirmata_h + // sets the output to 0, configures portConfigInputs + Firmata.setPinMode(i, OUTPUT); +#endif + } + } + +#ifdef FirmataExt_h + firmataExt.reset(); +#endif +} + +void printWifiStatus() { +#if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) + if ( WiFi.status() != WL_CONNECTED ) + { + DEBUG_PRINT( "WiFi connection failed. Status value: " ); + DEBUG_PRINTLN( WiFi.status() ); + } + else +#endif //defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) + { + // print the SSID of the network you're attached to: + DEBUG_PRINT( "SSID: " ); + +#if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) + DEBUG_PRINTLN( WiFi.SSID() ); +#endif //defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) + + // print your WiFi shield's IP address: + DEBUG_PRINT( "IP Address: " ); + +#if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) + IPAddress ip = WiFi.localIP(); + DEBUG_PRINTLN( ip ); +#endif //defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) + + // print the received signal strength: + DEBUG_PRINT( "signal strength (RSSI): " ); + +#if defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) + long rssi = WiFi.RSSI(); + DEBUG_PRINT( rssi ); +#endif //defined(ARDUINO_WIFI_SHIELD) || defined(WIFI_101) + + DEBUG_PRINTLN( " dBm" ); + } +} + +/*============================================================================== + * SETUP() + *============================================================================*/ + +void setup() +{ + /* + * WIFI SETUP + */ + DEBUG_BEGIN(9600); + + /* + * This statement will clarify how a connection is being made + */ + DEBUG_PRINT( "ConfigurableFirmataWiFi will attempt a WiFi connection " ); +#if defined(WIFI_101) + DEBUG_PRINTLN( "using the WiFi 101 library." ); +#elif defined(ARDUINO_WIFI_SHIELD) + DEBUG_PRINTLN( "using the legacy WiFi library." ); +#elif defined(HUZZAH_WIFI) + DEBUG_PRINTLN( "using the HUZZAH WiFi library." ); + //else should never happen here as error-checking in wifiConfig.h will catch this +#endif //defined(WIFI_101) + + /* + * Configure WiFi IP Address + */ +#ifdef STATIC_IP_ADDRESS + DEBUG_PRINT( "Using static IP: " ); + DEBUG_PRINTLN( local_ip ); + //you can also provide a static IP in the begin() functions, but this simplifies + //ifdef logic in this sketch due to support for all different encryption types. + stream.config( local_ip ); +#else + DEBUG_PRINTLN( "IP will be requested from DHCP ..." ); +#endif + + /* + * Configure WiFi security + */ +#if defined(WIFI_WEP_SECURITY) + while (wifiStatus != WL_CONNECTED) { + DEBUG_PRINT( "Attempting to connect to WEP SSID: " ); + DEBUG_PRINTLN(ssid); + wifiStatus = stream.begin( ssid, wep_index, wep_key, SERVER_PORT ); + delay(5000); // TODO - determine minimum delay + if (++wifiConnectionAttemptCounter > WIFI_MAX_CONN_ATTEMPTS) break; + } + +#elif defined(WIFI_WPA_SECURITY) + while (wifiStatus != WL_CONNECTED) { + DEBUG_PRINT( "Attempting to connect to WPA SSID: " ); + DEBUG_PRINTLN(ssid); + wifiStatus = stream.begin(ssid, wpa_passphrase, SERVER_PORT); + delay(5000); // TODO - determine minimum delay + if (++wifiConnectionAttemptCounter > WIFI_MAX_CONN_ATTEMPTS) break; + } + +#else //OPEN network + while (wifiStatus != WL_CONNECTED) { + DEBUG_PRINTLN( "Attempting to connect to open SSID: " ); + DEBUG_PRINTLN(ssid); + wifiStatus = stream.begin(ssid, SERVER_PORT); + delay(5000); // TODO - determine minimum delay + if (++wifiConnectionAttemptCounter > WIFI_MAX_CONN_ATTEMPTS) break; + } +#endif //defined(WIFI_WEP_SECURITY) + + DEBUG_PRINTLN( "WiFi setup done" ); + printWifiStatus(); + + /* + * FIRMATA SETUP + */ + Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION); + +#ifdef FirmataExt_h +#ifdef DigitalInputFirmata_h + firmataExt.addFeature(digitalInput); +#endif +#ifdef DigitalOutputFirmata_h + firmataExt.addFeature(digitalOutput); +#endif +#ifdef AnalogInputFirmata_h + firmataExt.addFeature(analogInput); +#endif +#ifdef AnalogOutputFirmata_h + firmataExt.addFeature(analogOutput); +#endif +#ifdef ServoFirmata_h + firmataExt.addFeature(servo); +#endif +#ifdef I2CFirmata_h + firmataExt.addFeature(i2c); +#endif +#ifdef OneWireFirmata_h + firmataExt.addFeature(oneWire); +#endif +#ifdef StepperFirmata_h + firmataExt.addFeature(stepper); +#endif +#ifdef SerialFirmata_h + firmataExt.addFeature(serial); +#endif +#ifdef FirmataReporting_h + firmataExt.addFeature(reporting); +#endif +#ifdef FirmataScheduler_h + firmataExt.addFeature(scheduler); +#endif +#ifdef FirmataEncoder_h + firmataExt.addFeature(encoder); +#endif +#endif + /* systemResetCallback is declared here (in ConfigurableFirmata.ino) */ + Firmata.attach(SYSTEM_RESET, systemResetCallback); + + // ConfigurableFirmataWiFi communicates with WiFi shields over SPI. Therefore all + // SPI pins must be set to IGNORE. Otherwise Firmata would break SPI communication. + // Additional pins may also need to be ignored depending on the particular board or + // shield in use. + + for (byte i = 0; i < TOTAL_PINS; i++) { +#if defined(ARDUINO_WIFI_SHIELD) + if (IS_IGNORE_WIFI_SHIELD(i) + #if defined(__AVR_ATmega32U4__) + || 24 == i // On Leonardo, pin 24 maps to D4 and pin 28 maps to D10 + || 28 == i + #endif //defined(__AVR_ATmega32U4__) + ) { +#elif defined (WIFI_101) + if (IS_IGNORE_WIFI101_SHIELD(i)) { +#elif defined (HUZZAH_WIFI) + // TODO + if (false) { +#else + if (false) { +#endif + Firmata.setPinMode(i, PIN_MODE_IGNORE); + } + } + + //Set up controls for the Arduino WiFi Shield SS for the SD Card +#ifdef ARDUINO_WIFI_SHIELD + // Arduino WiFi, Arduino WiFi Shield and Arduino Yun all have SD SS wired to D4 + pinMode(PIN_TO_DIGITAL(4), OUTPUT); // switch off SD card bypassing Firmata + digitalWrite(PIN_TO_DIGITAL(4), HIGH); // SS is active low; + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + pinMode(PIN_TO_DIGITAL(53), OUTPUT); // configure hardware SS as output on MEGA +#endif //defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + +#endif //ARDUINO_WIFI_SHIELD + + // start up Network Firmata: + Firmata.begin(stream); + systemResetCallback(); // reset to default config +} + +/*============================================================================== + * LOOP() + *============================================================================*/ +void loop() +{ +#ifdef DigitalInputFirmata_h + /* DIGITALREAD - as fast as possible, check for changes and output them to the + * stream buffer using Firmata.write() */ + digitalInput.report(); +#endif + + /* STREAMREAD - processing incoming message as soon as possible, while still + * checking digital inputs. */ + while (Firmata.available()) { + Firmata.processInput(); +#ifdef FirmataScheduler_h + if (!Firmata.isParsingMessage()) { + goto runtasks; + } + } + if (!Firmata.isParsingMessage()) { +runtasks: scheduler.runTasks(); +#endif + } + + // TODO - ensure that Stream buffer doesn't go over 60 bytes + +#ifdef FirmataReporting_h + if (reporting.elapsed()) { +#ifdef AnalogInputFirmata_h + /* ANALOGREAD - do all analogReads() at the configured sampling interval */ + analogInput.report(); +#endif +#ifdef I2CFirmata_h + // report i2c data for all device with read continuous mode enabled + i2c.report(); +#endif +#ifdef FirmataEncoder_h + // report encoders positions if reporting enabled. + encoder.report(); +#endif + } +#endif +#ifdef StepperFirmata_h + stepper.update(); +#endif +#ifdef SerialFirmata_h + serial.update(); +#endif + + // keep the WiFi connection live. Attempts to reconnect automatically if disconnected. + stream.maintain(); +} diff --git a/src/I2CFirmata.h b/src/I2CFirmata.h index 88fcfa1..e837a7b 100644 --- a/src/I2CFirmata.h +++ b/src/I2CFirmata.h @@ -13,8 +13,8 @@ See file LICENSE.txt for further informations on licensing terms. - ServoFirmata.cpp has been merged into this header file as a hack to avoid having to - include Servo.h for every arduino sketch that includes ConfigurableFirmata. + I2CFirmata.cpp has been merged into this header file as a hack to avoid having to + include Wire.h for every arduino sketch that includes ConfigurableFirmata. Last updated by Jeff Hoefs: January 23rd, 2015 */ diff --git a/src/OneWireFirmata.cpp b/src/OneWireFirmata.cpp index b43fcbd..80cf5ae 100644 --- a/src/OneWireFirmata.cpp +++ b/src/OneWireFirmata.cpp @@ -1,6 +1,7 @@ /* OneWireFirmata.cpp - Firmata library Copyright (C) 2012-2013 Norbert Truchsess. All rights reserved. + Copyright (C) 2016 Jeff Hoefs. 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 diff --git a/src/OneWireFirmata.h b/src/OneWireFirmata.h index fbd8a56..9c68aef 100644 --- a/src/OneWireFirmata.h +++ b/src/OneWireFirmata.h @@ -1,6 +1,7 @@ /* OneWireFirmata.h - Firmata library Copyright (C) 2012-2013 Norbert Truchsess. All rights reserved. + Copyright (C) 2016 Jeff Hoefs. 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 diff --git a/src/SerialFirmata.cpp b/src/SerialFirmata.cpp index 72a3805..f1df1d6 100644 --- a/src/SerialFirmata.cpp +++ b/src/SerialFirmata.cpp @@ -1,6 +1,6 @@ /* SerialFirmata.cpp - Firmata library - Copyright (C) 2015 Jeff Hoefs. All rights reserved. + Copyright (C) 2015-2016 Jeff Hoefs. 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 diff --git a/src/utility/WiFi101Stream.cpp b/src/utility/WiFi101Stream.cpp new file mode 100644 index 0000000..c494105 --- /dev/null +++ b/src/utility/WiFi101Stream.cpp @@ -0,0 +1,4 @@ +/* + * Implementation is in WiFi101Stream.h to avoid linker issues. Legacy WiFi and modern WiFi101 + * both define WiFiClass which will cause linker errors whenever Firmata.h is included. + */ diff --git a/src/utility/WiFi101Stream.h b/src/utility/WiFi101Stream.h new file mode 100644 index 0000000..eb95cf5 --- /dev/null +++ b/src/utility/WiFi101Stream.h @@ -0,0 +1,259 @@ +/* + WiFi101Stream.h + An Arduino Stream that wraps an instance of a WiFi101 server. For use + with Arduino WiFi 101 shield, Arduino MKR1000 and other boards and + shields that are compatible with the Arduino WiFi101 library. + + Copyright (C) 2015-2016 Jesse Frush. 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 + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See file LICENSE.txt for further informations on licensing terms. + */ + +#ifndef WIFI101_STREAM_H +#define WIFI101_STREAM_H + +#include +#include +#include + + +class WiFi101Stream : public Stream +{ +private: + WiFiServer _server = WiFiServer(23); + WiFiClient _client; + + //configuration members + IPAddress _local_ip; + uint16_t _port = 0; + uint8_t _key_idx = 0; //WEP + const char *_key = nullptr; //WEP + const char *_passphrase = nullptr; //WPA + char *_ssid = nullptr; + + inline int connect_client() + { + if( !( _client && _client.connected() ) ) + { + WiFiClient newClient = _server.available(); + if( !newClient ) + { + return 0; + } + + _client = newClient; + } + return 1; + } + + inline bool is_ready() + { + uint8_t status = WiFi.status(); + return !( status == WL_NO_SHIELD || status == WL_CONNECTED ); + } + +public: + WiFi101Stream() {}; + + // allows another way to configure a static IP before begin is called + inline void config(IPAddress local_ip) + { + _local_ip = local_ip; + WiFi.config( local_ip ); + } + + // get DCHP IP + inline IPAddress localIP() + { + return WiFi.localIP(); + } + + inline bool maintain() + { + if( connect_client() ) return true; + + stop(); + int result = 0; + if( WiFi.status() != WL_CONNECTED ) + { + if( _local_ip ) + { + WiFi.config( _local_ip ); + } + + if( _passphrase ) + { + result = WiFi.begin( _ssid, _passphrase); + } + else if( _key_idx && _key ) + { + result = WiFi.begin( _ssid, _key_idx, _key ); + } + else + { + result = WiFi.begin( _ssid ); + } + } + if( result == 0 ) return false; + + _server = WiFiServer( _port ); + _server.begin(); + return result; + } + +/****************************************************************************** + * Connection functions with DHCP + ******************************************************************************/ + + //OPEN networks + inline int begin(char *ssid, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + int result = WiFi.begin( ssid ); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + + //WEP-encrypted networks + inline int begin(char *ssid, uint8_t key_idx, const char *key, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _key_idx = key_idx; + _key = key; + + int result = WiFi.begin( ssid, key_idx, key ); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + + //WPA-encrypted networks + inline int begin(char *ssid, const char *passphrase, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _passphrase = passphrase; + + int result = WiFi.begin( ssid, passphrase); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + +/****************************************************************************** + * Connection functions without DHCP + ******************************************************************************/ + + //OPEN networks with static IP + inline int begin(char *ssid, IPAddress local_ip, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _local_ip = local_ip; + + WiFi.config( local_ip ); + int result = WiFi.begin( ssid ); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + + //WEP-encrypted networks with static IP + inline int begin(char *ssid, IPAddress local_ip, uint8_t key_idx, const char *key, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _local_ip = local_ip; + _key_idx = key_idx; + _key = key; + + WiFi.config( local_ip ); + int result = WiFi.begin( ssid, key_idx, key ); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + + //WPA-encrypted networks with static IP + inline int begin(char *ssid, IPAddress local_ip, const char *passphrase, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _local_ip = local_ip; + _passphrase = passphrase; + + WiFi.config( local_ip ); + int result = WiFi.begin( ssid, passphrase); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + +/****************************************************************************** + * Stream implementations + ******************************************************************************/ + + inline int available() + { + return connect_client() ? _client.available() : 0; + } + + inline void flush() + { + if( _client ) _client.flush(); + } + + inline int peek() + { + return connect_client() ? _client.peek(): 0; + } + + inline int read() + { + return connect_client() ? _client.read() : -1; + } + + inline void stop() + { + _client.stop(); + } + + inline size_t write(uint8_t byte) + { + if( connect_client() ) _client.write( byte ); + } +}; + +#endif //WIFI101_STREAM_H diff --git a/src/utility/WiFiStream.cpp b/src/utility/WiFiStream.cpp new file mode 100644 index 0000000..f7e0fca --- /dev/null +++ b/src/utility/WiFiStream.cpp @@ -0,0 +1,4 @@ +/* + * Implementation is in WiFiStream.h to avoid linker issues. Legacy WiFi and modern WiFi101 both + * define WiFiClass which will cause linker errors whenever Firmata.h is included. + */ diff --git a/src/utility/WiFiStream.h b/src/utility/WiFiStream.h new file mode 100644 index 0000000..fdcb483 --- /dev/null +++ b/src/utility/WiFiStream.h @@ -0,0 +1,258 @@ +/* + WiFiStream.h + An Arduino Stream that wraps an instance of a WiFi server. For use + with legacy Arduino WiFi shield and other boards and sheilds that + are compatible with the Arduino WiFi library. + + Copyright (C) 2015-2016 Jesse Frush. 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 + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See file LICENSE.txt for further informations on licensing terms. + */ + +#ifndef WIFI_STREAM_H +#define WIFI_STREAM_H + +#include +#include +#include + +class WiFiStream : public Stream +{ +private: + WiFiServer _server = WiFiServer(23); + WiFiClient _client; + + //configuration members + IPAddress _local_ip; + uint16_t _port = 0; + uint8_t _key_idx = 0; //WEP + const char *_key = nullptr; //WEP + const char *_passphrase = nullptr; //WPA + char *_ssid = nullptr; + + inline int connect_client() + { + if( !( _client && _client.connected() ) ) + { + WiFiClient newClient = _server.available(); + if( !newClient ) + { + return 0; + } + + _client = newClient; + } + return 1; + } + + inline bool is_ready() + { + uint8_t status = WiFi.status(); + return !( status == WL_NO_SHIELD || status == WL_CONNECTED ); + } + +public: + WiFiStream() {}; + + // allows another way to configure a static IP before begin is called + inline void config(IPAddress local_ip) + { + _local_ip = local_ip; + WiFi.config( local_ip ); + } + + // get DCHP IP + inline IPAddress localIP() + { + return WiFi.localIP(); + } + + inline bool maintain() + { + if( connect_client() ) return true; + + stop(); + int result = 0; + if( WiFi.status() != WL_CONNECTED ) + { + if( _local_ip ) + { + WiFi.config( _local_ip ); + } + + if( _passphrase ) + { + result = WiFi.begin( _ssid, _passphrase); + } + else if( _key_idx && _key ) + { + result = WiFi.begin( _ssid, _key_idx, _key ); + } + else + { + result = WiFi.begin( _ssid ); + } + } + if( result == 0 ) return false; + + _server = WiFiServer( _port ); + _server.begin(); + return result; + } + +/****************************************************************************** + * Connection functions with DHCP + ******************************************************************************/ + + //OPEN networks + inline int begin(char *ssid, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + int result = WiFi.begin( ssid ); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + + //WEP-encrypted networks + inline int begin(char *ssid, uint8_t key_idx, const char *key, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _key_idx = key_idx; + _key = key; + + int result = WiFi.begin( ssid, key_idx, key ); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + + //WPA-encrypted networks + inline int begin(char *ssid, const char *passphrase, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _passphrase = passphrase; + + int result = WiFi.begin( ssid, passphrase); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + +/****************************************************************************** + * Connection functions without DHCP + ******************************************************************************/ + + //OPEN networks with static IP + inline int begin(char *ssid, IPAddress local_ip, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _local_ip = local_ip; + + WiFi.config( local_ip ); + int result = WiFi.begin( ssid ); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + + //WEP-encrypted networks with static IP + inline int begin(char *ssid, IPAddress local_ip, uint8_t key_idx, const char *key, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _local_ip = local_ip; + _key_idx = key_idx; + _key = key; + + WiFi.config( local_ip ); + int result = WiFi.begin( ssid, key_idx, key ); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + + //WPA-encrypted networks with static IP + inline int begin(char *ssid, IPAddress local_ip, const char *passphrase, uint16_t port) + { + if( !is_ready() ) return 0; + + _ssid = ssid; + _port = port; + _local_ip = local_ip; + _passphrase = passphrase; + + WiFi.config( local_ip ); + int result = WiFi.begin( ssid, passphrase); + if( result == 0 ) return 0; + + _server = WiFiServer( port ); + _server.begin(); + return result; + } + +/****************************************************************************** + * Stream implementations + ******************************************************************************/ + + inline int available() + { + return connect_client() ? _client.available() : 0; + } + + inline void flush() + { + if( _client ) _client.flush(); + } + + inline int peek() + { + return connect_client() ? _client.peek(): 0; + } + + inline int read() + { + return connect_client() ? _client.read() : -1; + } + + inline void stop() + { + _client.stop(); + } + + inline size_t write(uint8_t byte) + { + if( connect_client() ) _client.write( byte ); + } +}; + +#endif //WIFI_STREAM_H