Introduction: SmartCityZen Recycle With HX711
SCZ Recycle is a system for monitoring your waste production. The purpose of the system is to increase the awareness of how our daily behavior has impact on the planet and the environment.
I installed it in my home and in just two days we realized that we have produced over 7.46 kg of rubbish!
We are a family but we have calculated quickly that our impact in the city in one year is almost 1 ton of waste that someone will have to manage and dispose !!!
This perhaps allows us to see the infamous TAX ON WASTE like a correct contribution that my family must give to the city that hosts us.
Step 1: What Do You Need?
FOR TRANSMITTER (Arduino)
n. 1 HX711 is a breakout board that interfaces with the load cells of a scale, reads the data and transmits it to the Arduino. It ‘a very inexpensive component (from 0.5 € to 2.5 €)
n.1 RF Receiver and n.1 RF Transmitter 433MHz
Cost a few Euros
n.1 Arduino or compatible (I used a Luigino 1000Pads you see in the picture)
n.1 kitchen scale than those with a max. of 5/7 Kg weight.(Normally in a waste basket “under the sink” There are 1.5 to 3 kg of waste)
A bit of cables and a breadboard.
FOR THE RECEIVER
n.1 Arduino or compatible (I used a Luigino 1000Pads that you see in the picture)
n.1 LCD Display 1602
Step 2: Transmitter System
Take off the scale (it is held together by a few screws), inside you’ll find something like in the picture
It is the load cell.
4 wires are connected to it that are the 4 points of a Wheatstone bridge into practice by applying a voltage of 2 of these wires you can read a voltage change on other 2 as a function of the pressure at which the load cell is subjected. in practice: greater the weight, greater is the change in voltage.
These 4 wires are connected to an electronic base inside the balance and connect to 4 points designated as follows:
E + : Excitation voltage +
E- : Excitation voltage –
S + : Signal +
S- : Signal –
Just connect these four wires to our at HX711 respective pin namely: E + with E +, E- with E-, A + with A + and S- with A-.
At this point we have to connect the HX711 and the RF transmitter from 433Mhz with Arduino
See Fritzing Picture...
For software...
First you need to install a library in Arduino for HX711:
HX711 Library
and for other function:
RF Transmission:
Manchester Library
Power Saving...
JeeLib
Step 3: Scale Calibration
There is a small code help that I changed from the examples of the library, there is a sketch for calibration but to me it was easier to proceed to trial with this sketch, then install the library and upload the sketch.
Opening the Arduino Serial Monitor will see that begin to read in sequence the value of the balance, no object will mark the weight of 0.0 Kg.
Now take an object (a glass, an apple what you will) weight it with a kitchen scale and then place it on the connected scale in Arduino.
By changing constant: valoredicalibrazione at line 22 you will see that the weight shown in the Serial Monitor will change, make several attempts until you find the value that gives the correct weight of the object (may be expressed in grams and not Kg).
When the value is equal to the reading on the kitchen scale made before the system is calibrated !!!
Now you can try any other object confirming the correct reading.
<br>
/*Questo sketch consente la calibrazione di una bilancia con HX711<p> This example code uses bogde's excellent library: <a href="https://github.com/bogde/HX711" rel="nofollow"> https://github.com/bogde/HX711 > bogde's library is released under a GNU GENERAL PUBLIC LICENSE</a></p> The HX711 does one thing well: read load cells. The breakout board is compatible with any wheat-stone bridge based load cell which should allow a user to measure everything from a few grams to tens of tons. Arduino pin A0 -> HX711 SCLK Arduino pin A1 -> HX711 DAT o DOUT Arduino 5V -> HX711 VCC Arduino GND -> HX711 GND la scheda può essere alimentata da 2.7V a 5.0V */ #include "HX711.h" #define valoredicalibrazione -7050.0 //Questo è il valore da modificare fino a raggiungere la corretta misura può essere negativo o positivo HX711 scale(A1, A0); //il parametro "gain" HX711(Dout,Sck,gain) se omesso assume il valore di default di 128 void setup() { Serial.begin(9600); Serial.println("HX711 scale demo"); scale.set_scale(valoredicalibrazione); //Seleziona il parametro di calibrazione scale.tare(); //Azzera la tara Serial.println("Letture:"); } void loop() { Serial.print("Lettura: "); Serial.print(scale.get_units(), 2); //scale.get_units() returns a float Serial.print(" Kg"); //You can change this to kg but you'll need to refactor the calibration_factor Serial.println(); }
Step 4: TX SKETCH (transmitter)
#include <HX711.h>
#include <JeeLib.h>
#include <Manchester.h>
ISR(WDT_vect) {Sleepy::watchdogEvent();}
// HX711.DOUT - pin #A1 // HX711.PD_SCK - pin #A0 /* * How to Calibrate Your Scale
1. Call set_scale() with no parameter. 2. Call tare() with no parameter. 3. Place a known weight on the scale and call get_units(10). 4. Divide the result in step 3 to your known weight. You should get about the parameter you need to pass to set_scale. 5. Adjust the parameter in step 4 until you get an accurate reading. */ // HX711 (Dout,Sck) HX711 scale(A1, A0); // parameter "gain" is ommited; the default value 128 is used by the library</p><p>#define TX_PIN 6 //pin where your transmitter is connected #define BUFFER_SIZE 50 #define LED_PIN 13 #define CELL_PIN A0//*********** SERIAL NUMBER *********** char SerialSens[ ]="SCZRE0364"; //*************************************
int volt=0; char messaggio[32]; unsigned char data[BUFFER_SIZE]=""; char msg[BUFFER_SIZE]; char msg2[10]; char msg3[10]; char msg4[10]; float carica=0; char vuota[32]=""; int offset_scale=53;
// How often do we do readings? long time = 0; // int timeBetweenReadings = 500; // We want a reading every 200 ms;
void setup() { Serial.begin(9600); man.workAround1MhzTinyCore(); //add this in order for transmitter to work with 1Mhz Attiny85/84 man.setupTransmit(TX_PIN, MAN_600); pinMode ( LED_PIN, OUTPUT); pinMode ( TX_PIN, OUTPUT); Serial.println("HX711 Demo");
Serial.println("Before setting up the scale:"); Serial.print("read: \t\t"); Serial.println(scale.read()); // print a raw reading from the ADC</p><p> Serial.print("read average: \t\t"); Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC</p><p> Serial.print("get value: \t\t"); Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight (not set yet)</p><p> Serial.print("get units: \t\t"); Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight (not set) divided // by the SCALE parameter (not set yet) </p><p> scale.set_scale(291.00); // this value is obtained by calibrating the scale with known weights; see the README for details scale.tare(); // reset the scale to 0</p><p> Serial.println("After setting up the scale:");</p><p> Serial.print("read: \t\t"); Serial.println(scale.read()); // print a raw reading from the ADC</p><p> Serial.print("read average: \t\t"); Serial.println(scale.read_average(20)); // print the average of 20 readings from the ADC</p><p> Serial.print("get value: \t\t"); Serial.println(scale.get_value(5)); // print the average of 5 readings from the ADC minus the tare weight, set with tare()</p><p> Serial.print("get units: \t\t"); Serial.println(scale.get_units(5), 1); // print the average of 5 readings from the ADC minus tare weight, divided // by the SCALE parameter set with set_scale</p><p> Serial.println("Readings:"); }
void loop() { Serial.print("\t| PESO:\t"); float peso=-scale.get_units(10); if (peso>-3 && peso<3) peso=0; Serial.print(peso, 0);Serial.println(" gr."); delay(50); dtostrf(peso, 4, 1,msg2); float risultato=readVcc(); dtostrf(risultato, 4, 0,msg4); carica=risultato/1000; dtostrf(carica, 1, 3,msg4);
strcpy(msg,""); strcat(msg, "SN:"); strcat(msg, SerialSens); strcat(msg, "PE:"); strcat(msg, msg2); strcat(msg, "BT:"); strcat(msg, msg4); for (int i=0;i<=BUFFER_SIZE;i++) { data[i]=msg[i]; } digitalWrite(LED_PIN, true); //Lampeggia il led al ricevimento del messaggio delay(10); digitalWrite(LED_PIN, false); man.transmitArray(BUFFER_SIZE,data); scale.power_down(); // put the ADC in sleep mode Sleepy::loseSomeTime(30000); scale.power_up(); }
float readVcc() { // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }
Obviously at line 71 change the value with what you got during calibration.
The sketch is based on the SmartCityZen project's transmission protocol, and then compared to the single waste control functionality there are some redundant information sent (for example the sensor code or battery volt).
In this way, however, the transmitted data can be read from SCZ Station and transferred via the Internet on SmartCityZen Web server and shared through the portal.
The sketch sends to the receiver every 30 seconds the weight of waste, this value can be changed simply changing the value of this command
Sleepy :: loseSomeTime (30000);
Modifying 30000 mS up to a max value of 60000 mS, which provides a pause of 1 minute, to increase it and make for example a send every 3 minutes using the following syntax:
Sleepy :: loseSomeTime (60000); Sleepy :: loseSomeTime (60000);<br>Sleepy :: loseSomeTime (60000);
Calling 3 times the command.
Step 5: Receiver System
The receiver system requires the Arduino connected with the 1602 display and the RF receiver to 433 MHz according to the wiring diagram.
And this is the sketch to load:
/* ------------------------------------------------------------------------------- // Monitoraggio produzione rifiuti casalinghi con SCZRE con display LCD 16x2 1602 con registrazione in EPROM del totrifiuti e dell'ultima pesata// */ #include <LiquidCrystal.h> #include <SPI.h> #include <SD.h> #include <Manchester.h> #include <string.h> #include <EEPROMex.h> // Connections: // rs (LCD pin 4) to Arduino pin 12 // rw (LCD pin 5) to Arduino pin 11 // enable (LCD pin 6) to Arduino pin 10 // LCD pin 15 to Arduino pin 13 // LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2 // Ricevitore RF connesso a pin 7 arduino LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2); int backLight = 13; // pin 13 will control the backlight</p><p>//Configurazione Libreria Manchester per trasmissione #define RX_PIN 7 #define BUFFER_SIZE 50 uint8_t buffer[BUFFER_SIZE]; unsigned char message[BUFFER_SIZE]; #define LED_PIN 13 char SensMessage[] = "SCZXX"; // Memorizzazione totale rifiuti String dataInizio = "02/01/2016"; int addressFloat = 0; int addressFloatPeso=5; boolean scarico=HIGH; float totRifiuti = 0.0; float precPeso = 0; float nowPeso = 0; void setup() { Serial.begin(9600); //EEPROM.writeFloat(addressFloat,totRifiuti); //EEPROM.writeFloat(addressFloatPeso,precPeso); pinMode(backLight, OUTPUT); digitalWrite(backLight, LOW); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off. lcd.begin(16, 2); // columns, rows. use 16,2 for a 16x2 LCD, etc. lcd.clear(); // start with a blank screen lcd.setCursor(0, 0); // set cursor to column 0, row 0 (the first row) lcd.print("SCZ Recycle"); // change this text to whatever you like. keep it clean. lcd.setCursor(0, 1); // set cursor to column 0, row 1 lcd.print("smartcityzen.it"); totRifiuti = EEPROM.readFloat(0); precPeso=EEPROM.readFloat(5); //Configurazione Manchester man.setupReceive(RX_PIN, MAN_600); man.beginReceiveArray(BUFFER_SIZE, buffer);
delay(500); lcd.clear(); // start with a blank screen lcd.setCursor(0, 0); // set cursor to column 0, row 0 (the first row) lcd.print("Attendi"); }
void loop() {if (man.receiveComplete()) { uint8_t receivedSize = 0; Serial.println("Ricevuto: "); digitalWrite(LED_PIN, HIGH); delay(100); digitalWrite(LED_PIN, LOW); for (int i = 0; i < BUFFER_SIZE; i++) {message[i] = char(buffer[i]); Serial.print(char(message[i])); } Serial.println(); Serial.print("SENSORE: "); for (int t = 0; t < 5; t++) { SensMessage[t] = message[t + 3]; } String messstr = String(SensMessage); Serial.println(messstr);
if (messstr == "SCZRE") { Serial.println("Ricevuto un SCZ RECYCLING"); gestioneSCZRE(); } man.beginReceiveArray(BUFFER_SIZE, buffer); } else { lcd.setCursor(0, 0); lcd.print("TOT: "); lcd.print(totRifiuti+nowPeso); lcd.print(" KG"); Serial.print("totRifiuti:");Serial.println(totRifiuti); lcd.setCursor(0, 1); lcd.print("NOW: "); lcd.print(nowPeso); lcd.print(" KG"); Serial.print("nowPeso:");Serial.println(nowPeso); } } //---------------------------------SCZRE-------------------------- void gestioneSCZRE() { Serial.print("IN FUNZIONE: "); for (int i = 0; i < BUFFER_SIZE; i++) { Serial.print(char(message[i])); } String nowRifiuti = ""; Serial.print("nowRifiuti:");Serial.println(nowRifiuti); for (int i = 0; i < 5; i++) { nowRifiuti = nowRifiuti + char(message[i + 15]); Serial.print(char(message[i + 15])); } Serial.print("nowRifiuti:");Serial.println(nowRifiuti); nowPeso = nowRifiuti.toFloat(); if (precPeso==0) { precPeso=nowPeso; } if (nowPeso<0.1 && scarico==LOW) { totRifiuti=totRifiuti+precPeso; EEPROM.writeFloat(addressFloat,totRifiuti); EEPROM.writeFloat(addressFloatPeso,precPeso); scarico=HIGH; } if (nowPeso>1) { scarico=LOW; } Serial.print("nowPeso:");Serial.println(nowPeso); }
Step 6: CONCLUSIONS
And here are the pictures of the final project.
Actually because I want to use the TX system with a battery, I'have replaced Arduino's TX System with an ATMEGA328 on breadboard, reducing size and energy consumption.