Posts with «arduino shield» label

Hackaday Prize Entry: Arduino Video Display Shield

The Arduino is the standard for any introduction to microcontrollers. When it comes to displaying video, the bone stock Arduino Uno is severely lacking. There’s just not enough memory for a framebuffer, and it’s barely fast enough to race the beam. If you want video from an Arduino, it’s either going to be crappy, or you’re going to need some magic chips to make everything happen.

[MagicWolfi]’s 2017 Hackaday Prize entry consists of an video display shield that would be so easy to use that, according to the project description, it could be a substitute for the classic Blink sketch.

The project centers around the VLSI VS23S010D-L chip, which packs 1 Megabit SPI SRAM with serial and parallel interfaces. An integrated video display  sends the composite video signal to display, with the mode depending on how many colors and what resolution is desired: for instance, at 640×400 you can display 16 colors. As he describes it, not 4K video but definitely Joust. The chip expects 3.3 V logic so he made use of a MC74LVX50 hex buffer to tailor the Arduino’s 5 V. Currently he’s working on revision two of the shield, which will include SPI flash memory.

You can follow along with the project on or the current shield design can be found in [MagicWolfi]’s GitHub repository.

Filed under: The Hackaday Prize

Hackaday Prize Entry: A Tiva Shaped Like an Arduino

Texas Instruments’ Tiva C LaunchPad showcases TI’s ARM Cortex-M4F, a 32-bit, 80Mhz microcontroller based on the TM4C123GH6PM. The Tiva series of LaunchPads serve as TI’s equivalent of the Arduino Uno, and hovers at about the same price point, except with more processing power and a sane geometry for the GPIO pins.

The Tiva’s processor runs five times faster than standard ATMega328P, and it sports 40 multipurpose GPIO pins and multiple serial ports. Just like the Arduino has shields, the Tiva has Booster Packs, and TI offers a decent number of options—but nothing like the Arduino’s ecosystem.

[Jacob]’s Arduino-Tiva project, an entry in the Hackaday Prize, aims to reformat the Tiva by building a TM4C123GH6PM-based board using the same form 2″x 3″ factor as the Arduino, allowing the use of all those shields. Of course, an Arduino shield only uses two rows of pins, so [Jacob]’s board would position the spare pins at the end of the board and the shield would seat on the expected ones.

The finished project could be flashed by either the Arduino IDE or TI’s Energia platform, making it an easy next step for those who’ve already mastered Arduinos but are looking for more power.

Filed under: The Hackaday Prize

Scissors Make Great Automatic Cable Cutters

The team at [2PrintBeta] required a bunch of cables, heat shrink, and braid to be cut for their customers. They looked into an industrial cable cutter, but decided the price was a little too high, so they decided to make their own. They had a bunch of ideas for cutting: Using a razor blade?  Or a Dremel with a cutting wheel? What they came up with was a DIY cable cutter that uses a pair of scissors, a pair of stepper motors, a pair of 3D printed wheels and an Arduino.

The first thing the team had to do was to mount the scissors so they would cut reliably. One of the stepper motors was attached to a drive wheel that had a bolt mounted on it. This went through one of the scissors’ handles, the other handle was held in place on the machine using screws. The second stepper motor was used to rotate the wheels that drives the cable through to the correct length. [2PrintBeta] used a BAM&DICE shield and two DICE-STK stepper motor drivers on an Arduino Mega to control the cutter.

The [2PrintBeta] team are pretty good at doing things themselves, as we’ve seen previously with their DIY plastic bender. And again, with this automatic cable cutter, they’ve seen a need and resolved it using the things at their disposal and some DIY ingenuity.

Filed under: Microcontrollers, tool hacks

Arduino’s Long-Awaited Improved WiFi Shield

Announced at the 2014 Maker Faire in New York, the latest Arduino WiFi shield is finally available. This shield replaces the old Arduino WiFi shield, while providing a few neat features that will come in very handy for the yet-to-be-developed Internet of Things.

While the WiFi Shield 101 was announced a year ago, the feature set was interesting. The new WiFi shield supports 802.11n, and thanks to a few of Atmel’s crypto chip offerings, this shield is the first official Arduino offering to support SSL.

The new Arduino WiFi Shield 101 features an Atmel ATWINC1500 module for 802.11 b/g/n WiFi connectivity. This module, like a dozen or so other WiFi modules, handles the heavy lifting of the WiFi protocol, including TCP and UDP protocols, leaving the rest of the Arduino free to do the actual work. While the addition of 802.11n  will be increasingly appreciated as these networks become more commonplace, the speed offered by ~n isn’t really applicable; you’re not going to be pushing bits out of an Arduino at 300 Mbps.

Also included on the WiFi shield is an ATECC508A CryptoAuthentication chip. This is perhaps the most interesting improvement over the old Arduino WiFi shield, and allows for greater security for the upcoming Internet of Things. WiFi modules already in the space have their own support for SSL, including TI’s CC3200 series of modules, Particle‘s Internet of Things modules, and some support for the ESP8266.

Filed under: Arduino Hacks

APRS Tracking System Flies Your Balloons

Looking for a way to track your high-altitude balloons but don’t want to mess with sending data over a cellular network? [Zack Clobes] and the others at Project Traveler may have just the thing for you: a position-reporting board that uses the Automatic Packet Reporting System (APRS) network to report location data and easily fits on an Arduino in the form of a shield.

The project is based on an Atmel 328P and all it needs to report position data is a small antenna and a battery. For those unfamiliar with APRS, it uses amateur radio frequencies to send data packets instead of something like the GSM network. APRS is very robust, and devices that use it can send GPS information as well as text messages, emails, weather reports, radio telemetry data, and radio direction finding information in case GPS is not available.

If this location reporting ability isn’t enough for you, the project can function as a shield as well, which means that more data lines are available for other things like monitoring sensors and driving servos. All in a small, lightweight package that doesn’t rely on a cell network. All of the schematics and other information are available on the project site if you want to give this a shot, but if you DO need the cell network, this may be more your style. Be sure to check out the video after the break, too!

Filed under: radio hacks

Programmable Lithium Charger Shield for Arduino

Surely you need yet another way to charge your lithium batteries—perhaps you can sate your desperation with this programmable multi (or single) cell lithium charger shield for the Arduino<! Okay, so you’re not><em>hurting</em> for another method of juicing up your batteries. If you’re a regular around these parts of the interwebs, you’ll recall the <a href="">lithium charging guide</a> and that <a href="">rather incredible, near-encyclopedic rundown of both batteries and chargers</a>, which likely kept your charging needs under control.</p> <p>That said, this shield by Electro-Labs might be the perfect transition for the die-hard-’duino fanatic looking to migrate to tougher projects. The build features an LCD and four-button interface to fiddle with settings, and is based around an LT1510 constant current/constant voltage charger IC. You can find the schematic, bill of materials, code, and PCB design on the Electro-Labs webpage, as well as a brief rundown explaining how the circuit works. Still want to add on the design? Throw in <a href="">one of these Li-ion holders</a> for quick battery swapping action.</p> <p>[via <a href="">Embedded Lab</a>]</p><br />Filed under: <a href="">Arduino Hacks</a>, <a href="">Microcontrollers</a> <a><img src="" /></a> <img src="" />

Battery Shield Mounts Underneath The Arduino

So, what do you do when your Arduino project needs to operate in a remote area or as a portable device? There are LiPo battery shields available, and although they may work well, recharging requires access to a USB port. You can also go the 9v battery route plugged into the on-board regulator of the Arduino but the low mAh rating of a 9v won’t allow your project to stay running for very long. [AI] needed a quick-change battery option for his Arduino project and came up with what he is calling the AA Undershield.

As the name implies, AA sized batteries are used in the project, two of them actually. Yes, two AA batteries at 1.5v each would equal only 3 volts when connected in series. The Arduino needs 5v so [AI] decided to use a MAX756 DC-to-DC step-up regulator to maintain a steady stream of 5v. This article has some nice graphs showing the difference in performance between a 9v battery being stepped down to 5v verses two AA’s being bumped up to 5v.

The ‘under’ in Undershield comes from this shield being mounted underneath the Arduino, unlike every other shield on the planet. Doing so allows use of a standard 0.100″-spaced prototype PCB and is an easy DIY solution to that odd-sized space between the Arduino’s Digital 7 and 8 pins. The Arduino mounts to the Undershield via its normal mounting holes with the help of some aluminum stand offs.

[AI] did a great job documenting his build with schematics and lots of photos so that anyone that is interested in making one for themselves can do so with extreme ease.

Filed under: Arduino Hacks

Brushless Motor Controller Shield for Arduino

Brushless motors are ubiquitous in RC applications and robotics, but are usually driven with low-cost motor controllers that have to be controlled with RC-style PWM signals and don’t allow for much customization. While there are a couple of open-source brushless drivers already available, [neuromancer2701] created his own brushless motor controller on an Arduino shield.

[neuromancer2701]‘s shield is a sensorless design, which means it uses the back-EMF of the motor for feedback rather than hall effect sensors mounted on the motor. It may seem strange to leave those sensors unused but this allows for less expensive sensorless motors to work with the system. It also uses discrete FETs instead of integrated driver ICs, similar to other designs we have covered. Although he is still working on the back-EMF sensing in his firmware, the shield successfully drives a motor in open-loop mode.

The motor controller is commanded over the Arduino’s serial interface, and will support a serial interface to ROS (Robot Operating System) in the future. This shield could be a good alternative to hobby RC controllers for robots that need a customizable open-source motor controller. The PCB design and source code are available on GitHub.


Filed under: Arduino Hacks

Arduino DMX shield for Christmas projects



This shield allows to connect an Arduino with DMX equipment. It implements the RS485 interface to adapt the electrical levels needed for DMX connection.

This shield has been designed with flexibility in mind and allows the user to choose between several Arduino pins for digital input and output of DMX data, it supports a microSD slot and also has the serial connection to support a serial LCD display.

This design allows basic operation of DMX through simple pre programmed messages stored in the Arduino Sketch or, with the proper libraries and programming, it could well become a standalone system with playback capabilities of sequences stored on the microSD. When needed, this solution is also a suitable interface for a PC sending through a serial port the DMX commands.

DMX basics

This interfacing and communication standard has been developed to allow easier management of complex lighting systems. On stages and discos, many spots, pars, moving heads and other equipment need to be managed and controlled, but bringing power from a centralized panel rises many issues for safety and cabling complexity.

With DMX, each device has an integrated or external controller. A control system sends a specific message to each controller with a byte that the controller itself interprets according to its address and capabilities. Power supply becomes “local” and the communication is with a daisy chained cable that carries low voltage signals.

DMX data is sent in parallel to every controller connected and the address given to each controller allows each device to grab and interpret only the relevant information.

The transmission scheme has been designed for efficiency as DMX may drive up to 512 devices at the same time, with 40 complete transmission sets per second. To achieve this, with 8 bits, 1 start and 1 stop bit, speed has to be 250 kbps. The serial data starts with a header and then bytes are sent in sequence, starting from the first one.

If we have to send a new command to the controller with address 10, we need to send also the data relevant to the controllers from 1 to 9. The addressing system is based on position of the byte and each controller counts the incoming bytes, discarding the ones preceding and following its own byte.

It is also important to remember that each command received is always relevant, therefore to alter the state of a single controller, it is necessary to send valid commands to all the controllers that have a lower address. The sequence, however, may end when the address of the relevant controller has been reached (no need to send the sequence with data exceeding the relevant controller address).

The values from 0 to 255 initially represented the level of the light (0 = off, 255 = full brightness), but the adoption of DMX by other devices turned the meaning of the byte into other commands, eg. position, program selection, specific preset, activate feature and so on. Each manufacturer specifies the mapping between values and functions and sometimes a single byte is not enough to manage all the capabilities, therefore the device occupies an interval of addresses on the DMX bus and reads more than one byte, in sequence.


Shield schematics

This shield uses a MAX485 by Maxim to convert the signal levels from the Arduino digital pin to the RS485 differential simplex two wire plus ground connection. The MAX485 contains a receiver and a transmitter, with enabling signals. The /RE (pin 2) and OE (pin 3) – that enable reception and transmission – are with inverted levels, so that it is possible to use a single line and the two pins connected together to manage transmission direction. Pin 1 is Receive Output, pin 4 is Data Input, pin 6 and 7 are the differential outputs.

It is possible to choose between different Arduino D pins for each of the three signals needed: RO may be mapped onto D0 or D4, DI onto D1 or D3 and /RE+OE onto D2 or D5.

The other chip on the shield is an 74HC4050D that contains six buffers to match TTL levels from Arduino ICSP with the 3,3V required by the microSD. This is required just by microSD input lines because Arduino input correctly reads the 3,3V level supplied by microSD as a logic “1”.

The last bits of the schematics include a couple of LEDs connected to D7 and D8, a pushbutton on A1 and the serial connection for the LCD on A0/A2 (jumper selectable).


Before you proceed with this shield, you should decide the various jumpers positions; if no other shield is used with Arduino, you are free to choose any of the two positions available; when used with other shields, use the jumpers to avoid any conflict. Please note that ICSP is used with Ethernet shields as well, therefore the microSD slot might create conflicts if used with an Ethernet equipped solution.

DMX library 


This shield needs a specific library named DmxSimple.h available for download at ; with it you will find some examples. We also have two other sketches to let you experiment with this shield.

/* Welcome to DmxSimple. This library allows you to control DMX stage and
** architectural lighting and visual effects easily from Arduino. DmxSimple
** is compatible with the! DMX shield and all known DIY Arduino
** DMX control circuits.
** DmxSimple is available from:
** Help and support:       */

/* To use DmxSimple, you will need the following line. Arduino will
** auto-insert it if you select Sketch > Import Library > DmxSimple. 

Modified by Boris Landoni



const int jrde =  2;
const int jdi  =  3;
const int jro  =  4;
const int lr   =  7;
const int ly   =  8;

void setup() {

  pinMode(jrde, OUTPUT);
  pinMode(jdi,  OUTPUT);
  pinMode(jro,  INPUT);
  pinMode(lr, OUTPUT);
  pinMode(ly, OUTPUT);

  digitalWrite(jrde, HIGH);

  /* The most common pin for DMX output is pin 3, which DmxSimple
  ** uses by default. If you need to change that, do it here. */

  /* DMX devices typically need to receive a complete set of channels
  ** even if you only need to adjust the first channel. You can
  ** easily change the number of channels sent here. If you don't
  ** do this, DmxSimple will set the maximum channel number to the
  ** highest channel you DmxSimple.write() to. */

void loop() {
  int brightness;
  /* Simple loop to ramp up brightness */  
  for (brightness = 0; brightness <= 255; brightness++) {
    digitalWrite(lr, HIGH);
    /* Update DMX channel 1 to new brightness */
    //DmxSimple.write(1, brightness);
    DmxSimple.write(2, brightness);
    //DmxSimple.write(3, brightness);
    DmxSimple.write(4, 189);

    /* Small delay to slow down the ramping */
    digitalWrite(lr, LOW);





We also suggest to use Vixen ( to create sequences on a PC, synced with music, that are sent to Arduino over the serial port. The communication between Arduino and Vixen is managed by our sketch DMX_LightSequencing.

The purpose of this code is to allow the Arduino to use the 
generic serial output of vixen lights to control 5 channels of LEDs. 
Author: Matthew Strange
Created: 14 October 2010
Modifier: Ben Towner
Modified: 19-OCT-2010
Changes: Addition of 20 Digital On/Off Channels - Setup for Arduino Mega 2560
Modified by Boris Landoni



const int jrde =  2;
const int jdi  =  3;
const int jro  =  4;
const int lr   =  7;
const int ly   =  8;

#define DELAY    10

int i = 0;     // Loop counter
int incomingByte[25];   // array to store the 25 values from the serial port
int address=1;
int ch=16;
int k;

//setup the pins/ inputs & outputs
void setup()
  Serial.begin(9600);        // set up Serial at 9600 bps

  pinMode(jrde, OUTPUT);
  pinMode(jdi,  OUTPUT);
  pinMode(jro,  INPUT);
  pinMode(lr, OUTPUT);
  pinMode(ly, OUTPUT);

  digitalWrite(jrde, HIGH);

  /* The most common pin for DMX output is pin 3, which DmxSimple
  ** uses by default. If you need to change that, do it here. */

  /* DMX devices typically need to receive a complete set of channels
  ** even if you only need to adjust the first channel. You can
  ** easily change the number of channels sent here. If you don't
  ** do this, DmxSimple will set the maximum channel number to the
  ** highest channel you DmxSimple.write() to. */

  for (k=0; k= ch) {
    // read the oldest byte in the serial buffer:
      for (k=0; k

Wi-Fi Body Scale with Arduino

In this post we present the design of a scale that connects to the Internet and automatically sends weight info on a Google Document.

The project is composed of



Taking a look at the diagram, we can distinguish three sections:

one for handling digital inputs (two buttons and scale’s switch),
the LCD manager
the analog signal acquisition from load cells

You may notice that P1 and P2 buttons are respectively managed by Arduino’s A3 and A4 inputs (configured as digital), while the INT switch reads the A5 signal (digital as well).

The LCD display used in our project belongs to the family of those based on HD44780 chipset, equipped with seven-pin control (RW, D4, D5, D6, D7, RS and Enable). As you can see from the diagram, RW is permanently connected to ground so it’s only operating in writing mode.

D4, D5, D6 and D7 pins are respectively managed by 3, 5, 6 and 7 digital pins of the Arduino Uno; RS is managed by pin 8 and the Enable pin from pin A0 (this configuration will also be specified in the software).

Besides the power supply (a VCC connected to 5V) and the ground (GND), the display requires a level of voltage between 0 and 5 volts to adjust the contrast in the input pin VO (adjustment made through R6 potentiometer).

Finally the display has 2 pin (A and K respectively anode and cathode) for switching on the backlight: feeding the pin with a voltage of 5V, the backlight is turned on, otherwise it is off.

The switching on and off is handled via a push-button switch that connects or disconnects the ground from the cathode.

Finally let’s analyze the part that manages the analog signal from the load cells: this is done by INA125 integrated component, a high precision amplifier developed specifically for measuring tools like scales.

The IC is fitted with two pins (6 and 7) representing the input of the differential amplification stage. These pins are connected to the two ends of the Wheatstone bridge (which in our project correspond to two of the load cell pins).

As you can figure out, the differential signal coming from the bridge has an absolute value of just a few millivolts: our project requires an amplification of about 500 times, obtained with a 120 ohm resistor.

The amplified output is provided at pins 10 and 11 of INA125; these pins are connected to A1 analog of the Arduino board, which therefore will be used for reading the value ADC.

R1: 39 ohm
R2: 1 kohm
R3: 4,7 kohm
R4: 4,7 kohm
R5: 330 ohm
R6: Trimmer 10 kohm
R7: 4,7 kohm

C1: 100 nF 63 VL
C2: 100 µF 25 VL

U1: INA125

P1: Microswitch
P2: Microswitch

LCD: Display LCD 8×2


Hacking  the Velleman scale

Our system is designed to be matched to the high-capacity scale produced by Velleman. But you can using any scale usign 4 load cells. The original Velleman electronics and display must be phased out and replaced with our project.

The scale structure is made up of 4 load cells (arranged on the 4 corners), which are configured between them so as to create a single Wheatstone bridge.

To make the connection to our board you must disassemble the lower section of the scale in order to access the electronics.

Referring to Fig A, which shows the structure of the scale viewed from below, with a quick visual analysis is easy to figure out that some blue and red wires are connected to each other while the yellow wires are connected to the switches positioned on the front of the two cells that identify the presence of a person.

To hack the scale follow these steps:

  • unsolder or cut all the red and blue wires, push in short those that were already shorted previously,

  • unsolder or cut the yellow wires coming from the cells numbered 1 and 3, put them in parallel (possibly by welding), extend them and take them to the two terminals on the new INT printed board (Fig.B)

  • unsolder or cut the white wire that is referred to as G3 (Wheatstone bridge mass) on the original printed circuit, extend take it to terminal 1 on the new printed circuit;

  • unsolder or cut the white wire that is referred to as G2 (Wheatstone bridge positive) on the original printed circuit, extend take it to terminal 3 on the new printed circuit;

  • unsolder or cut the white wire that is referred to as G1 and G4 on the original printed circuit, extend take it to terminal 4 and 2 on the new printed circuit (differential signal on the Wheatstone bridge)


The Sketch

As for the LCD, Arduino provides a convenient library (<LiquidCrystal.h>) already supporting different kinds of LCD (both 8 and 16 chars for 2 lines) based on the parallel interface chipset HD44780.

After the inclusion of the library, you must initialize the connection to the display, through LiquidCrystal LCDDisplay (8, A0, 3, 5, 6, 7), in this command, the parameters passed to the function and indicate Arduino’s hardware pins used to connect RS, Enable, D4, D5, D6 and D7 pins of the display.

Depending on the Arduino setup could be necessary to execute LCDDisplay.begin (width, height) in which the parameters indicate the physical dimensions of the display: LCDDisplay.begin (8, 2) in this case.

The library makes available instructions:

  • LCDDisplay.setCursor (x, y) to position the cursor in a certain position
  • LCDDisplay.print (String) to print strings

Management of Arduino’s EEPROM is done by the <EEPROM.h> library  that, once included, provides the functions:

  • EEPROM.write (add, date) to write a byte in a particular cell and

  • (add) that the instead reads a byte from one cell (the add parameter specifies the address of the EEPROM cell).

Wi-Fi network and internet connection are managed thanks to the <WiServer.h> library; you just need to define some variables to configure the network (like IP’s and Network masks).

The adapter to connect and publish data on Google Documents shall operate as a Web Client: this configuration is done in the setup instruction WiServer.init (NULL) in which the NULL parameter specifies client mode.

You must create a function that will receive and handle the response from the server, this is done by the googlePublish.setReturnFunc  (Gestione_Risposte_Web) instruction  in our example. This function must be defined later in the code: in our example is void Gestione_Risposte_Web (char * data, int len) and receives as parameters both a pointer to a string containing the response and the length (in bytes) of the response.

Sending information requires to make a POST request to Google’s servers: WiServer library makes available a POSTrequest just to do this.

You must define the IP address of the server to which you want to connect (Google in our case) and define a structure of the POSTrequest (in our case, the variable is called googlePublish) containing the IP address of the server, the TCP / IP port the server name (, URL of POST execution and finally a function (SearchQuery in our case) that builds POST request body.


 Autori: Ingg. Tommaso Giusto e Ing. Alessandro Giusto

// Inclusione Libreria per Display LCD 8x2
#include <LiquidCrystal.h>
// Inclusione Libreria per EEPROM scheda
#include <EEPROM.h>
// Inclusione Libreria per Server Web WiFi
#include <WiServer.h>
// Inclusione Libreria per SD Card
//#include <SD.h>

// Definizione pin INPUT/OUTPUT
const int PinVPeso = A1;         // Ingresso analogico uscita peso
const int PinPulsanteP1 = A3;    // Ingresso pulsante P1 su A3
const int PinPulsanteP2 = A4;    // Ingresso pulsante P2 su A4
const int PinInterruttore = A5;  // Ingresso interruttore su A5

// Definizione/Inizializzazione PIN Display LCD
// LCD RS pin D8
// LCD Enable on pin A0
// LCD D4, D5, D6, D7 on pins D3, D5, D6, D7
// LCD R/W pin a massa
// LCD V0 pin trimmer tra +5V e massa
LiquidCrystal LCDDisplay (8, A0, 3, 5, 6, 7);

 Definizione struttura EEPROM

// Byte 0x000        Nome
// ...               Utente
// Byte 0x01F        000 (0x00 Carattere fine stringa)
// ...               
// ...               
// ...               
// Byte 0x120        Nome
// ...               Utente
// Byte 0x13F        009 (0x00 Carattere fine stringa)
#define StartNomiUtentiEEPROMADD          0x0000
#define EndNomiUtentiEEPROMADD            0x013F
#define DimensioneNomeUtenteEEPROMADD     32
#define NumMaxNomiUtenti                  10

// Byte 0x140        Parte Alta Peso Utente 000
// Byte 0x141        Parte Bassa Peso Utente 000
// ...               
// ...               
// ...               
// Byte 0x152        Parte Alta Peso Utente 009
// Byte 0x153        Parte Bassa Peso Utente 009
#define StartPesiUtentiEEPROMADD          0x0140
#define EndPesiUtentiEEPROMADD            0x0153
#define DimensionePesoUtenteEEPROMADD     2

#define PesoMIN                           100
#define PesoMAX                           2000
#define AnalogDifferenzaPesoMAX           15

#define CalibrazioneSensoreMIN            0
#define CalibrazioneSensoreMAX            80

 Definizione variabili globali

// Definizione Parametri Rete Wireless
#define WIRELESS_MODE_INFRA	1  // Infrastrutturata (basata su Access Point)
#define WIRELESS_MODE_ADHOC	2  // Ad-hoc (senza Access Point)

// Parametri di rete
unsigned char local_ip[] = {192, 168, 0, 89};      // Indirizzo IP
unsigned char gateway_ip[] = {192, 168, 0, 254};	    // Indirizzo gateway IP
unsigned char subnet_mask[] = {255, 255, 255, 0};   // Subnet Mask
const prog_char ssid[] PROGMEM = {"FlashMob"};	    // SSID access point

// Selezione tipo di cifratura rete Wireless
unsigned char security_type = 0;  // 0 -> nessuna cifratura
                                  // 1 -> cifratura WEP
                                  // 2 -> cifratura WPA
                                  // 3 -> cifratura WPA2

// Password cifratura per WPA/WPA2 (max. 64 cratteri)
const prog_char security_passphrase[] PROGMEM = {"12345678"};

// Password cifratura per WEP 128-bit keys
prog_uchar wep_keys[] PROGMEM = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

// Selezione tipo di rete Wireless infrastrutturata
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

// Variabili per lunghezza SSID e password di cifratura
unsigned char ssid_len;
unsigned char security_passphrase_len;

// Definizione Parametri Pubblicazione Google
// Indirizzo IP per server
uint8 google_ip[] = {209, 85, 229, 101};

// Richiesta POST verso GOOGLE
POSTrequest googlePublish (google_ip, 80, "", "", searchQuery);

// Stringa per eseguire pubblicazione
char newURL[] = {"/formResponse?formkey=dDFPcWhxNlZxMEpnUnhNdE5fT1lDcWc6MQ&ifq&entry.0.single=++++++++++++++++++++++++++++++++&entry.1.single=999,9&submit=Submit"};

// This function generates the body of our POST request
void searchQuery() {

// Indica presenza SD Card
//boolean presenzaSDCard;

// Inizializzazione Scheda
void setup() {
  // Inizializzo dimensioni LCD (8x2)
  LCDDisplay.begin (8, 2);

  // Inizializzo pin usati come INPUT/OUTPUT
  pinMode (PinInterruttore, INPUT);  
  pinMode (PinPulsanteP1, INPUT);
  pinMode (PinPulsanteP2, INPUT);

  // Se all'accensione rilevati tutti e 2 i pulsanti premuti
  if ((PulsantePremuto (PinPulsanteP1) == 1) &&
      (PulsantePremuto (PinPulsanteP2) == 1)) {
    // Segnalo inizializzazione in corso
    LCDDisplay.setCursor (0, 0);
    LCDDisplay.print ("Init EEP");
    LCDDisplay.setCursor (0, 1);
    LCDDisplay.print ("in corso");

    // Inizializzo EEPROM scheda
    // Attesa
    delay (500);
  // Inizializzo porta seriale
  Serial.begin (9600);  
  Serial.println ("Bilancia WiFi");
  Serial.println ("By Ingg. Tommaso e Alessandro Giusto");
  // Invio stato utenti

  // Segnalo Avvio Web
  LCDDisplay.setCursor (0, 0);
  LCDDisplay.print ("  Init  ");
  LCDDisplay.setCursor (0, 1);
  LCDDisplay.print ("  web   ");  

  // Inizializzo WiServer
  WiServer.init (NULL);
  WiServer.enableVerboseMode (false);

  // Inizializzazione richiesta POST (parametro indica funzione a cui verra' passata la risposta)
  googlePublish.setReturnFunc (Gestione_Risposte_Web);    

  // Inizializzo SD Card
  pinMode(10, OUTPUT);  
  presenzaSDCard = SD.begin (4);
  // Se inizializzazione SD fallita  
  if (presenzaSDCard == false)
    Serial.println ("Init SD FAULT!");
  // Se inizializzazione SD riuscita
    Serial.println ("Init SD OK!");

// Programma Principale
void loop() {
  // Ciclo infinito di esecuzione
  for (;;) {
    // Gestione Peso

    // Per circa 1 sec
    for (byte tmp = 0; tmp < 250; tmp++) {
      // Gestione programmazione seriale
      // Gestione WiServer
      // Attesa
      delay (4);
    }    // Chiusura ciclo for per circa 1 sec
  }    // Chiusura ciclo infinito di esecuzione

 Definizione funzioni

// Funzione Gestione Peso
void GestionePeso() {
  // Indice utente selezionato
  //    0,..,(NumMaxNomiUtenti-1) -> selezionato utente 1,..,NumMaxNomiUtenti
  //    0xFF -> nessun utente selezionato
  static int IndiceUtenteSelezionato = 0xFF;
  // Indica l'indice carattere visualizzato  
  static int IndiceCarattere = 0;
  String NomeUtenteSelezionato;
  int PesoUtenteSelezionato;
  int LunghezzaNomeUtenteSelezionato;
  int ValoreSensorePeso1, ValoreSensorePeso2;
  int ValoreSensorePesoTMP1, ValoreSensorePesoTMP2, ValoreSensorePesoTMP3, ValoreSensorePesoTMP4;
  static int CalibrazioneSensore;
  int CalibrazioneSensoreTMP;
  int PesoCalcolato;
  int tmp;

  // Se non premuto interruttore (utente non salito)
  if (PulsantePremuto (PinInterruttore) == 0) {
    // Leggo valore sensore per calibrazione
    CalibrazioneSensoreTMP = analogRead (PinVPeso);
    // Se valore sensore per calibrazione valido
    if ((CalibrazioneSensoreTMP >= (int) (CalibrazioneSensoreMIN)) &&
      (CalibrazioneSensoreTMP <= (int) (CalibrazioneSensoreMAX)))
      // Aggiorno valore sensore per calibrazione
      CalibrazioneSensore = CalibrazioneSensoreTMP;
  }    // Chiusura if non premuto interruttore (utente non salito)

  // Se premuto tasto 1
  if (PulsantePremuto (PinPulsanteP1) == 1) {
    // Azzero indice carattere visualizzato
    IndiceCarattere = 0;

    // Verifico tutte le posizioni utente
    for (tmp = 0; tmp < NumMaxNomiUtenti; tmp++) {
      // Seleziono utente selezionato
      switch (IndiceUtenteSelezionato) {
        // Se selezionato ultimo utente/nessun utente selezionato
        case (NumMaxNomiUtenti - 1): case 0xFF:
          // Seleziono primo utente
          IndiceUtenteSelezionato = 0;
          break;    // Chiusura case selezionato ultimo utente/nessun utente selezionato

        // Se selezionato altro utente
          // Seleziono prossimo utente
          break;    // Chiusura case nessun utente selezionato
      }    // Chiusura switch seleziono utente selezionato

      // Se trovato utente con nome non nullo
      if (LeggiNomeUtente (IndiceUtenteSelezionato).length() != 0x00)
        // Blocco ciclo for verifico tutte le posizioni utente
    }    // Chiusura ciclo for verifico tutte le posizioni utente

    // Se non trovato utente con nome non nullo
    if (tmp == NumMaxNomiUtenti)
      // Seleziono nessun utente
      IndiceUtenteSelezionato = 0xFF;
  }    // Chiusura if premuto tasto 1

  // Se utente selezionato
  if (IndiceUtenteSelezionato != 0xFF) {
    // Leggo nome/peso utente
    NomeUtenteSelezionato = LeggiNomeUtente (IndiceUtenteSelezionato);
    PesoUtenteSelezionato = LeggiPesoUtente (IndiceUtenteSelezionato);
    // Calcolo lunghezza nome utente    
    LunghezzaNomeUtenteSelezionato = NomeUtenteSelezionato.length();
    // Seleziono lunghezza nome utente
    switch (LunghezzaNomeUtenteSelezionato) {
      case 0:
        // Indico nessun utente selezionato
        IndiceUtenteSelezionato = 0xFF;
      case 1: case 2: case 3: case 4: case 5: case 6: case 7:
        LCDDisplay.setCursor ((8 - LunghezzaNomeUtenteSelezionato) / 2, 0);
        LCDDisplay.print (NomeUtenteSelezionato);
      case 8:
        LCDDisplay.setCursor (0, 0);
        LCDDisplay.print (NomeUtenteSelezionato);
        if ((IndiceCarattere + 8) > LunghezzaNomeUtenteSelezionato)
          IndiceCarattere = 0;

        LCDDisplay.setCursor (0, 0);
        LCDDisplay.print (&NomeUtenteSelezionato[IndiceCarattere]);

        // Messaggio scorrevole
        if ((IndiceCarattere + 8) > LunghezzaNomeUtenteSelezionato)
          IndiceCarattere = 0;
    }    // Chiusura switch seleziono lunghezza nome utente
    LCDDisplay.setCursor (0, 1);
    LCDDisplay.print (PesoUtenteSelezionato / 1000);
    LCDDisplay.print ((PesoUtenteSelezionato % 1000) / 100);
    LCDDisplay.print ((PesoUtenteSelezionato % 100) / 10);
    LCDDisplay.print (".");
    LCDDisplay.print (PesoUtenteSelezionato % 10);    
    LCDDisplay.print (" Kg");

    // Se premuto interruttore (utente salito)
    if (PulsantePremuto (PinInterruttore) == 1) {
      LCDDisplay.setCursor (0, 1);
      LCDDisplay.print ("..... Kg");

      // Leggo valore analogico peso
      for (;;) {
        // Attesa
        delay (500);
        // Eseguo prima lettura peso
        ValoreSensorePesoTMP1 = analogRead (PinVPeso);
        delay (125);
        ValoreSensorePesoTMP2 = analogRead (PinVPeso);
        delay (125);
        ValoreSensorePesoTMP3 = analogRead (PinVPeso);
        delay (125);
        ValoreSensorePesoTMP4 = analogRead (PinVPeso);
        delay (125);
        ValoreSensorePeso1 = ((ValoreSensorePesoTMP1 + ValoreSensorePesoTMP2 + ValoreSensorePesoTMP3 + ValoreSensorePesoTMP4) / 4);

        // Attesa
        delay (500);
        // Eseguo seconda lettura peso
        ValoreSensorePesoTMP1 = analogRead (PinVPeso);
        delay (125);
        ValoreSensorePesoTMP2 = analogRead (PinVPeso);
        delay (125);
        ValoreSensorePesoTMP3 = analogRead (PinVPeso);
        delay (125);
        ValoreSensorePesoTMP4 = analogRead (PinVPeso);
        delay (125);
        ValoreSensorePeso2 = ((ValoreSensorePesoTMP1 + ValoreSensorePesoTMP2 + ValoreSensorePesoTMP3 + ValoreSensorePesoTMP4) / 4);

        // Se peso stabilizzato
        if ((ValoreSensorePeso1 <= ValoreSensorePeso2) && ((ValoreSensorePeso2 - ValoreSensorePeso1) < (int) (AnalogDifferenzaPesoMAX)) ||
            (ValoreSensorePeso1 > ValoreSensorePeso2) && ((ValoreSensorePeso1 - ValoreSensorePeso2) < (int) (AnalogDifferenzaPesoMAX)))
          // Blocco ciclo for leggo valore analogico peso
      }    // Chiusura ciclo for leggo valore analogico peso

      // Calcolo peso utente
      PesoCalcolato = (int) (ValoreSensorePeso2 - CalibrazioneSensore);
      PesoCalcolato = (PesoCalcolato + (((int) (PesoCalcolato * (int) (10))) / (int) (62)));

//    68.1 KG
//    642   con calibrazione: 62 -> Veff = 580

      // Se peso valido
      if ((PesoCalcolato >= (int) (PesoMIN)) && (PesoCalcolato <= (int) (PesoMAX))) {
        // Memorizzo peso utente
        ScriviPesoUtente (IndiceUtenteSelezionato, PesoCalcolato);

        // Visualizzo peso calcolato
        LCDDisplay.setCursor (0, 1);
        LCDDisplay.print (PesoCalcolato / 1000);
        LCDDisplay.print ((PesoCalcolato % 1000) / 100);
        LCDDisplay.print ((PesoCalcolato % 100) / 10);
        LCDDisplay.print (".");
        LCDDisplay.print (PesoCalcolato % 10);    
        LCDDisplay.print (" Kg");

        // Richiedo pubblicazione        
        LCDDisplay.setCursor (0, 0);
        LCDDisplay.print ("Pubblic?");

        // Per massimo 5 secondi attendo pressione tasto 2
        for (tmp = 0; tmp < 10; tmp++) {
          // Se premuto tasto 2
          if (PulsantePremuto (PinPulsanteP2) == 1) {
            // Indico pubblicazione in corso     
            LCDDisplay.setCursor (0, 0);
            LCDDisplay.print ("Pubblic.");
            LCDDisplay.setCursor (0, 1);
            LCDDisplay.print ("  wait  ");

            // Eseguo pubblicazione
            for (tmp = 0; tmp < NomeUtenteSelezionato.length(); tmp++) {
              newURL[76 + tmp] = NomeUtenteSelezionato.charAt(tmp);
              if (newURL[76 + tmp] == ' ')
                newURL[76 + tmp] = '+';
            newURL[124] = ((PesoCalcolato / 1000) + 0x30);
            newURL[125] = (((PesoCalcolato % 1000) / 100) + 0x30);      
            newURL[126] = (((PesoCalcolato % 100) / 10) + 0x30);      
            newURL[128] = ((PesoCalcolato % 10) + 0x30);      
            delay (500);
            // Blocco ciclo for
          delay (500);          
        }    // Chiusura ciclo for per massimo 5 secondi attendo pressione tasto 2
        // Se SD rilevata
        if (presenzaSDCard == true) {
          // Verifico/Creo directory BilanciaWiFi
          if (!(SD.exists ("BilanciaWiFi")))
            SD.mkdir ("BilanciaWiFi");

          // Memorizzo il peso su file
          File filePeso;
          // Apro il file in scrittura
          char nomeFilePeso[50] = {"BilanciaWiFi/"};
          for (tmp = 0; tmp < NomeUtenteSelezionato.length(); tmp++) {
            charTmp[0] = NomeUtenteSelezionato.charAt(tmp);
            strcat (nomeFilePeso, charTmp);
          strcat (nomeFilePeso, ".txt");          
          filePeso = (nomeFilePeso, FILE_WRITE);

          // Se apertura file OK
          if (filePeso) {
            // Memorizzo il peso
            filePeso.print ((PesoCalcolato / 1000) + 0x30);
            filePeso.print (((PesoCalcolato % 1000) / 100) + 0x30);
            filePeso.print (((PesoCalcolato % 100) / 10) + 0x30);
            filePeso.print (".");
            filePeso.print ((PesoCalcolato % 10) + 0x30);
            filePeso.print (" Kg");
            // Chiudo il file:

        LCDDisplay.setCursor (0, 0);
        LCDDisplay.print ("  Step  ");
        LCDDisplay.setCursor (0, 1);
        LCDDisplay.print ("  off   ");

        // Attendo utente scende dalla bilancia
        for (;;) {
          // Se non premuto interruttore (utente non salito)
          if (PulsantePremuto (PinInterruttore) == 0)
      }    // Chiusura if peso valido
    }    // Chiusura if premuto interruttore (utente salito)
  }    // Chiusura if utente selezionato

  // Se nessun utente selezionato
  else {
    LCDDisplay.setCursor (0, 0);
    LCDDisplay.print (" Chose  ");
    LCDDisplay.setCursor (0, 1);
    LCDDisplay.print (" user   ");
  }    // Chiusura if nessun utente selezionato

// Funzione Gestione Seriale
void GestioneSeriale() {
  String comandoRicevutoString = "";
  int numeroUtenteRicevuto;
  String nomeUtenteRicevuto = "";

  // Se ricevuti dati dalla porta seriale
  if (Serial.available()) {
    // Attendo tutti i dati
    delay (250);

    // Ricevo i dati
    while (Serial.available())
      comandoRicevutoString += (char) (;

    // Invio comando ricevuto    
    Serial.println (comandoRicevutoString);

    // Se ricevuti almeno 15 caratteri
    if (comandoRicevutoString.length() >= 15) {
      // Se ricevuto comando programmazione nome utente (NOME_UTENTE_xx=)USER_NAME_01=Boris
      if ((comandoRicevutoString.substring (0, 12).equals("P_USER_NAME_")) &&
          (isdigit(comandoRicevutoString.charAt (12))) &&
          (isdigit(comandoRicevutoString.charAt (13)))) {
        // Estraggo numero utente ricevuto
        numeroUtenteRicevuto = (((comandoRicevutoString.charAt (12) - 0x30) * 10) +
                                (comandoRicevutoString.charAt (13) - 0x30));
        // Se ricevuto numero utente corretto
        if ((numeroUtenteRicevuto >= 1) && (numeroUtenteRicevuto <= NumMaxNomiUtenti)) {
          // Estraggo nome utente
          nomeUtenteRicevuto = comandoRicevutoString.substring (15);
          // Se nome troppo lungo
          if (nomeUtenteRicevuto.length() > DimensioneNomeUtenteEEPROMADD)
            // Tronco il nome
            nomeUtenteRicevuto = nomeUtenteRicevuto.substring (0, DimensioneNomeUtenteEEPROMADD);

          // Memorizzo il nome
          ScriviNomeUtente (numeroUtenteRicevuto - 1, nomeUtenteRicevuto);
          // Azzero il relativo peso
          AzzeraPesoUtente (numeroUtenteRicevuto - 1);
          // Indico OK
          Serial.println ("OK");
          // Invio su  porta seriale lo stato utenti
          // Termino funzione

    // Indico errore
    Serial.println ("FAULT");
    // Termino funzione

// Invia su  porta seriale lo stato utenti
void InviaProgrammazioneUtenti() {
  for (int numeroUtente = 0; numeroUtente < NumMaxNomiUtenti; numeroUtente++) {
    Serial.print ("Us. ");
    Serial.print ((numeroUtente + 1) / 10);
    Serial.print ((numeroUtente + 1) % 10);
    Serial.print (": ");
    Serial.println (LeggiNomeUtente (numeroUtente));

// Funzione Gestione WiServer
void GestioneWiServer() {
  // Gestione WiServer

// Gestione diverse risposte provenienti dal WEB
void Gestione_Risposte_Web (char* data, int len) {

  // Print the data returned by the server
  // Note that the data is not null-terminated, may be broken up into smaller packets, and 
  // includes the HTTP header. 
  while (len-- > 0) {


// Scrive il nome di un utente
// INPUT:   Posizione utente (0,..,9)
//          Nome utente in formato stringa
// OUTPUT:  -
// Note:    -
void ScriviNomeUtente (int NomePosition, String NomeUtente) {
  // Azzero nome utente selezionato
  AzzeraNomeUtente (NomePosition);

  // Scrivo i caratteri nome utente selezionato
  for (int tmp = 0; tmp < NomeUtente.length(); tmp++)
    EEPROM.write (StartNomiUtentiEEPROMADD + tmp +
                  (NomePosition * DimensioneNomeUtenteEEPROMADD), NomeUtente.charAt(tmp));

// Legge il nome di un utente
// INPUT:   Posizione utente (0,..,9)
// OUTPUT:  Nome utente in formato stringa
// Note:    -
String LeggiNomeUtente (int NomePosition) {
  String NomeUtente = "";
  char NomeUtenteChar;

  // Leggo i caratteri nome utente selezionato
  for (int tmp = 0; tmp < DimensioneNomeUtenteEEPROMADD; tmp++) {
    // Leggo singolo carattere
    NomeUtenteChar = (StartNomiUtentiEEPROMADD + tmp +
                                  (NomePosition * DimensioneNomeUtenteEEPROMADD));

    // Se trovato carattere fine nome
    if (NomeUtenteChar == 0x00)
      // Blocco ciclo for leggo i caratteri nome utente selezionato

    // Accodo carattere letto
    NomeUtente = NomeUtente + NomeUtenteChar;

  // Ritorno il nome
  return (NomeUtente);

// Azzera il nome di un utente
// INPUT:   Posizione utente (0,..,9)
// OUTPUT:  -
// Note:    -
void AzzeraNomeUtente (int NomePosition) {
  // Azzero caratteri nome utente selezionato
  for (int tmp = 0; tmp < DimensioneNomeUtenteEEPROMADD; tmp++)
    EEPROM.write (StartNomiUtentiEEPROMADD + tmp +
                  (NomePosition * DimensioneNomeUtenteEEPROMADD), 0); 

// Scrive il peso di un utente
// INPUT:   Posizione utente (0,..,9)
//          Peso utente
// OUTPUT:  -
// Note:    -
void ScriviPesoUtente (int PesoPosition, int PesoUtente) {
  // Memorizzo peso nome utente
  EEPROM.write (StartPesiUtentiEEPROMADD + 
                (PesoPosition * DimensionePesoUtenteEEPROMADD), (byte) (PesoUtente >> 8));
  EEPROM.write (StartPesiUtentiEEPROMADD + 1 +
                (PesoPosition * DimensionePesoUtenteEEPROMADD), (byte) (PesoUtente & 0x00FF));

// Legge il peso di un utente
// INPUT:   Posizione utente (0,..,9)
// OUTPUT:  Peso utente
// Note:    -
int LeggiPesoUtente (int PesoPosition) {
  // Ritorno il peso
  return (((int) ( (StartPesiUtentiEEPROMADD +
                               (PesoPosition * DimensionePesoUtenteEEPROMADD))) << 8) +
           (int) ( (StartPesiUtentiEEPROMADD + 1 +
                               (PesoPosition * DimensionePesoUtenteEEPROMADD))));

// Azzera il peso di un utente
// INPUT:   Posizione utente (0,..,9)
// OUTPUT:  -
// Note:    -
void AzzeraPesoUtente (int PesoPosition) {
  // Azzero peso nome utente
  ScriviPesoUtente (PesoPosition, 0);

// Inizializza EEPROM scheda
// INPUT:   -
// OUTPUT:  -
// Note:    -
void InizializzaEEPROM() {
  // Azzero i nomi/pesi di tutti gli utenti
  for (int tmp = 0; tmp < NumMaxNomiUtenti; tmp++) {
    AzzeraNomeUtente (tmp);
    AzzeraPesoUtente (tmp);

// Verifica lo stato di un pulsante
// INPUT:   Pin pulsante
// OUTPUT:  Stato pulsante    0 -> pulsante non premuto
//                            1 -> pulsante premuto
// Note:    -
int PulsantePremuto (int PinPulsante) {
  if (digitalRead (PinPulsante) == LOW)
    return (1);
    return (0);


Install the WiShield libraries

To work properly, the Wifi shield requires specific libraries that must be installed in the Arduino IDE used to compile the sources so you’ll need to put these libraries in the Arduino libraries path.

The library supports multiple operating modes (APP_WEBSERVER, APP_WEBCLIENT, APP_SOCKAPP, APP_UDPAPP and APP_WISERVER).

The default value is APP_WEBSERVER, which runs on most Arduino systems but has several limitations. The main limitation is that it can’t function both as a client and server simultaneously.

It is therefore recommended the APP_WISERVER (in the library named “WiServer.h“) which allows the Arduino shield equipped with Wi-Fi to be configured and operated either as a Web Server as a Web Client.

In the first case, you can serve connection requests from external web clients and send HTML pages in response, in the second it will be possible to connect to a web server and send GET or POST requests.

To configure the WiShield library as APP_WISERVER you must open the apps-conf.h file, comment the “#define“ APP_WEBSERVER row and uncomment the “#define” of APP_WISERVER row.

Something like:

/ / # define APP_WEBSERVER

/ / # define APP_WEBCLIENT

/ / # define APP_SOCKAPP

/ / # define APP_UDPAPP


Configuring publishing

Performing data publication on Google Documents requires three distinct steps:

  1. Configuring Wi-Fi network access;
  2. Creating a Google Docs form module: each module is characterized by an identifying 34 characters string – FormKey) and each field is characterized by an identification number (called Entry).
  3. Inserting the FormKey / Entry in the Arduino software.

Configuring network parameters

First you must configure and update the IP address, Subnet Mask, Gateway IP and Network SSID, then select the encryption mode and change password information for your network. Save all, compile and run the upload Software tab.

Creating the Google  module doc

Create a form on Google Docs, modify the form with two fields (username and weight, both of type string) and save the job. (the result is something like the one shown in Figure). In our case, we left the default file name and called the two fields “User Name” and “User weight”

take note of this key string because then it will be inserted in the Arduino software: as you can see from the picture, the link shows the form key assigned to the module (in this example, the link is: which implies that the form assigned key is “dDFPcWhxNlZxMEpnUnhNdE5fT1lDcWc6MQ”);


Clicking on the link will open a new page that shows the data entry form: within this form text fields are marked with “entry.0.single“, “entry.1.single“, etc … (basically with an integer id)

 To see which number has been assigned to our fields you need to display the HTML source of the form (the result is something like the one shown in this Figure).

You can easily find the ID numbers assigned to different fields (in our example “entry.0.single” is the “Name” and “entry.1.single” is the “weight“).

Take note of this information because it will be included in the source Arduino as well.

Formkey / entry

Once you have created the form, the Arduino source will be configured so that it is compatible with the form you created.

A variable is defined in Arduino source named newURL[]: the variable is initialized with a standard format then modified to perform publication (refer to Figure 11 to identify it in the code).

Replace the default values with those obtained at the time of the creation of the form, compile and download it to the Arduino board.




How to program user names

The configuration of user names can be made via serial port and Serial Monitor. To program it, connect to the board (via USB cable) and open the Arduino Serial Monitor. As a first step the card sends a summary of the current configuration.

To program a new user name you must send a string in the format “P_USER_NAME_xx = User Name” with xx between 01 and 10 ID (put an empty string to delete the selected user.) If all the posted information is correct, this is confirmed by the message “Ok” otherwise “Fault”.


Using the scale

The scale software is able to distinguish up to 10 users (each identified by its name) and, for each one, it stores the last measured weight.

If you want to clear the memory (which we recommend at first use) is sufficient to hold down either of the two buttons (the display indicates the operation with “EEP init in progress”).

Later, you can configure names following the procedure described in the “Programming user names” section.

As the next step the Web management interface will start and the system will enter its normal operation. The user selection is done by pressing button P1.

Going over the scale starts the weighing procedure (lasting several seconds): weight is displayed and stored and the scale asks for publishing on the web: by pressing P2 the operation is performed.