Saturday, June 6, 2015

Arduino Hx711 Digital Scale

After finding a broken scale in the trash at work, I decided to remove the load cell and build a digital scale with an Arduino. The output of the load cell is too minute for an Arduino to read on it's own, so I picked up a <$5 amplifier module online to convert the reading into a signal the Arduino can read. The Hx711 module is a 24 bit ADC, which offers high resolution and amplification. It's also designed for scale / load cell applications, so talking to it requires a minimum of code.

Connections are fairly simple. You will need a 4 wire load cell, and those typically have Green, White, Red, and Black wires.

Connect as follows:
Red: E +
White: A +
Green: A -
Black: E -

B- & B+ could be used for another load cell, but we are not using these.

If you get negative readings (-12g), reverse the A+ and A- wires.

On the other side of the module:

GND: Arduino GND
DT: Arduino A2 (can change this in code)
SCK: Arduino A3 (can change this in code)
VCC: Arduino +5


You will need to download the library files (the library files at dfrobot will not install properly using the add library function, these will).

Per the instructions at dfrobot, you may have to adjust a value in the Hx711.h file in the library to zero your scale. Mine did not need that.


/* sample for digital weight scale of hx711
 * library design: Weihong Guan (@aguegu)
 * library host on

// Hx711.DOUT - pin #A2
// Hx711.SCK - pin #A3

#include <Hx711.h>
Hx711 scale(A2, A3);

void setup() {

void loop() {
  Serial.print(scale.getGram(), 1);
  Serial.println(" g");

To put the measured value into a variable for further processing, replace the code in void loop with:

float value = scale.getGram();
Serial.println(" g");

Thursday, June 4, 2015

Arduino Westminster Chimes Door Bell

I was repairing a Heath Zenith SL-6180 wireless doorbell, in the process, figured out how to manually trigger the bells without using the remote. I then thought, why not have an arduino trigger the bells based on motion sense, floor pad sensor, or pushbutton. The door bell I'm using plays a very nice version of Westminster Chimes. Open it up, find the transistor labeled Q5 on the board and attach a wire to the base (center pin) to an arduino output. Connect a wire from battery negative to Arduino negative. When you want the chimes to ring, pulse the pin you have connected to Q5 - digitalWrite(pin, HIGH);

Other applications could be a audio notification when you get an email, a tweet, or completion of a task.

Monday, June 1, 2015

Wifi Weather Web Server

It's Alive, It's Alive. Ok, sounds better if done with a Dr. Frankenstein accent, but the Arduino WiFi wireless weather Server is alive. Starting with a Arduino UNO, we then stacked a Arduino WiFi shield, a adafruit Lithium Polymer battery shield, and a Sparkfun Protoshield with a Embedded Adventures BME280 breakout and a 3.3v - 5v level shifter. A 5v solar panel is on it's way to keep this charged,

Arduino UNO
Arduino WiFi
Adafruit LIPO
Sparkfun Protoshield
Embedded Adventures BME280 (schematics)
Embedded Adventures Level Shifter

You can see it in real time at (be patient)

Code (Video below)
#include <SPI.h>
#include <WiFi.h>

#include <BME280_MOD-1022.h>

#include <Wire.h>

IPAddress dns(192, 168, 254, 254);
IPAddress ip(192, 168, 254, 16);  
IPAddress gateway(192, 168, 254, 254); 
IPAddress subnet(255, 255, 255, 0); 

float temp, humidity,  pressure, pressureMoreAccurate, tempF, inHg, rH;
double tempMostAccurate, humidityMostAccurate, pressureMostAccurate;

char ssid[] = "your ssid";      // your network SSID (name)
char pass[] = "your password";   // your network password
int keyIndex = 0;                 // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;

WiFiServer server(80);

// print out the measurements

void printCompensatedMeasurements(void) {

char buffer[80];

  temp      = BME280.getTemperature();
  humidity  = BME280.getHumidity();
  pressure  = BME280.getPressure();
  pressureMoreAccurate = BME280.getPressureMoreAccurate();  // t_fine already calculated from getTemperaure() above
  tempMostAccurate     = BME280.getTemperatureMostAccurate();
  humidityMostAccurate = BME280.getHumidityMostAccurate();
  pressureMostAccurate = BME280.getPressureMostAccurate();

  Serial.print("Temperature  ");
  tempF = tempMostAccurate * 1.8 + 32.0;
  Serial.print(" ");
  Serial.print("Humidity     ");
  rH = humidityMostAccurate;
  Serial.println(" %");

  Serial.print("Pressure     ");
  inHg = pressureMostAccurate * 0.0295299830714;
  Serial.print(inHg, 2);
  Serial.println(" in. Hg");

void setup() {
  //Initialize serial and wait for port to open:
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);

  String fv = WiFi.firmwareVersion();
  if ( fv != "1.1.0" )
    Serial.println("Please upgrade the firmware");

  // attempt to connect to Wifi network:

  WiFi.config(ip, dns, gateway, subnet); 
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
  // you're connected now, so print out the status:

void loop() {
  uint8_t chipID;
  chipID = BME280.readChipId();
  // find the chip ID out just for fun
  //Serial.print("ChipID = 0x");
  //Serial.print(chipID, HEX);
  // need to read the NVM compensation parameters
  // Need to turn on 1x oversampling, default is os_skipped, which means it doesn't measure anything
  BME280.writeOversamplingPressure(os1x);  // 1x over sampling (ie, just one sample)
  // example of a forced sample.  After taking the measurement the chip goes back to sleep
  while (BME280.isMeasuring()) {
  // read out the data - must do this before calling the getxxxxx routines
  // Example for "indoor navigation"
  // We'll switch into normal mode for regular automatic samples
  BME280.writeStandbyTime(tsb_0p5ms);        // tsb = 0.5ms
  BME280.writeFilterCoefficient(fc_16);      // IIR Filter coefficient 16
  BME280.writeOversamplingPressure(os16x);    // pressure x16
  BME280.writeOversamplingTemperature(os2x);  // temperature x2
  BME280.writeOversamplingHumidity(os1x);     // humidity x1
  while (1) {
    while (BME280.isMeasuring()) {

    // read out the data - must do this before calling the getxxxxx routines
    delay(2000); // do this every 5 seconds
  // listen for incoming clients
  WiFiClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c =;
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println("<!DOCTYPE HTML>");
          // output the value of each sensor

            client.print("Temperature ");
            client.println("<br />");
            client.print("Humidity ");
            client.print(" %");
            client.println("<br />");
            client.print("Pressure ");
            client.print(" in. Hg");
            client.println("<br />");
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
    // give the web browser time to receive the data

    // close the connection:
    Serial.println("client disonnected");


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.println(" dBm");

Upgrading Arduino WiFi Shield Firmware

I have a couple of new wifi projects I'm working on, and was getting the message to upgrade my firmware on the WiFi shield, as well as the browser was not able to load the web page on the Arduino. I've tried upgrading firmware before, with unhappy results, as the firmware files on Github (where most of the instructionals send you) were defective and bricked my shield. I just finished upgrading 3 shields, including the one that was bricked, so I'm confident these instructions work.

How do you know if you have a problem?

The following code in the example wifi webserver sketch will send a message to the Serial Monitor that it's time for a firmware upgrade:

  String fv = WiFi.firmwareVersion();
  if ( fv != "1.1.0" )
    Serial.println("Please upgrade the firmware");

If it is out of date, you'll need a couple of things:

  • USB cable with mini-B plug (Playstation3) not micro-B (Kindle).
  • Atmel Flip Software
  • wifi firmware files (\libraries\WiFi\extras\binary - no need to download) 

Find the jumper on your wifi shield (should be disabled) and enable it (before plugging in the cable).

Plug the mini-USB cable into the wifi shield. I recommend having the WiFi shield plugged into a unpowered Arduino to prevent static issues. Plug the other end of the mini-USB into your computer.

Set your path to include the directory where batchisp.exe (from the Flip install) is located. Mine happened to be C:\Program Files (x86)\Atmel\Flip 3.4.7\bin

To do this, just open a command line windows and type:

path=%path%;C:\Program Files (x86)\Atmel\Flip 3.4.7\bin

the cd to the folder where your wifi firmware files are located.

cd yourarduinofolder\libraries\WiFi\extras\binary

in the command line window, enter:

batchisp.exe -device AT32UC3A1256 -hardware usb -operation erase f memory flash blankcheck loadbuffer wifi_dnld.elf program verify start reset 0

you should see the following:

Shield responds with solid Blue LED.
Press the shield reset button.  Blue LED extinguishes.
Unplug the mini-USB cable and plug it back in again.

Now type the following in the command line window:

batchisp.exe -device AT32UC3A1256 -hardware usb -operation erase f memory flash blankcheck loadbuffer wifiHD.elf program verify start reset 0

you should see the following:

Press the Shield reset button.
Remove the short from J3
Unplug the micro-USB cable

Now when you upload the wifi server example, you will no longer get the out of date firmware message, and your web browser will be able to connect to the arduino ip address shown in the serial monitor.

Thanks to the instructions at which helped greatly.