Arduino scale & display for food dispenser & weight calculation

Status
Not open for further replies.

iqasi096

Member
Hello,

I have been looking at using a scale amplifier (similar to the HX-711) with an ESP32 & Teensy 3.2 (similar to most Arduinos) to weigh a food carrying dispenser before and after dispensing to find the weight dispensed by the container. I have connected a button to trigger the dispensing of the components where in essence it will turn a DC motor to turn an auger & dispense but that is not the main topic of this thread.

My issue is with the calculation of the weight before the button is pressed. I am using the ESP32 as the Master which is measuring the weight from the amplifier and sending it to the Teensy 3.2 slave in accordance to the I2C protocol as found here:

ESP32 code:

Code:
/**
   A simple sketch to test and demo the dispenser's current features
*/

#include "Dispenser.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>

// Const
const int dispensingTimout = 5000; //in milliseconds
int prevWeight = 0;

// Wifi constants
const char* wifiSsid = "Crunchy";
const char* wifiPassword = "muffin4me";
const int httpConnectionTimeout = 500;
const char* cartServiceURL = "http://10.0.0.88:8080/Cart";
const char* pulseServiceURL = "http://10.0.0.88:8080/Pulse";

static char weightstr[15];
Dispenser dp;

void setup()
{
  Wire.begin();               
  Serial.begin(115200);
  // Initialise dispenser

  // Connect to WiFi
  WiFi.begin(wifiSsid, wifiPassword);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi...");
  }

  Serial.println("Connected to WiFi...");
  Serial.println(WiFi.localIP());

  dp.begin();
}

void loop()
{
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient pulseClient;
    pulseClient.setConnectTimeout(httpConnectionTimeout);
    pulseClient.begin(pulseServiceURL);
    int pulseResponseCode = pulseClient.GET();
    pulseClient.end();
       
        
        // Keep filling container until timout is reached
        unsigned long startTime = millis();
        //while (millis() - startTime < dispensingTimout) {
          float weight = dp.getWeight();
          dtostrf(weight, 7, 2,weightstr);
          Serial.println(weightstr);
          Wire.beginTransmission(8); // transmit to device #8
          Wire.write(weightstr);
          Wire.endTransmission();    // stop transmitting


          String xml1 = "<CartItem xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.datacontract.org/2004/07/Dispenser.WebService.Model\">\r\n";
          String xml2a = "    <CardId>";
          String xml2b = "</CardId>\r\n";
          String xml3a = "    <MachineId>";
          String xml3b = "</MachineId>\r\n";
          String xml4a = "    <Weight>";
          String xml4b = "</Weight>\r\n";
          String xml5 = "</CartItem>";

          String payload = xml1 + xml2a + xml2b + xml3a + xml3b + xml4a + xml4b + xml5;
          //String payload = xml1 + xml2a + cardID + xml2b + xml3a + machineID + xml3b + xml4a + weightString + xml4b + xml5;
          Serial.println(payload);

          HTTPClient webclient;
          webclient.setConnectTimeout(httpConnectionTimeout);
          webclient.begin(cartServiceURL);
          webclient.addHeader("Content-Type", "application/xml");
          webclient.addHeader("Accept", "application/xml");
          int httpResponseCode = webclient.POST(payload);

          if (httpResponseCode == 200) {
            Serial.println("Sending data: success");
          } else {
            Serial.println("Sending data: failed");
          }
          webclient.end();
       }
}

Teensy 3.2 Code:

Code:
/**
   A simple sketch to test and demo the dispenser's current features
*/

#include "DispenserData.h"
#include "DispenserUI.h"
#include "Dispenser.h"
#include <Wire.h>

// Const
const int dispensingTimout = 5000; //in milliseconds
float weight; 
float prevWeight = 0;

Dispenser dp;

void setup()
{
  dp.begin();
  // Show product screen at startup
  dp.clearScreen();
  dp.showProductScreen();
  Serial.begin(115200);
}

void loop()
{
      // Continuosly check for rfid cards
      if (dp.isCardPresent()) {
        Serial.print("CardID: ");
        Serial.println(dp.getCardID());
        // If one is detected, toggle LED
        // and display sale screen
        dp.buzz();
        dp.clearScreen();
        dp.showSaleScreen(0);
        dp.ledOn();

        
        // Keep filling container until timout is reached
         unsigned long startTime = millis();
         while (millis() - startTime < dispensingTimout) {
            Wire.begin(8);                // join i2c bus with address #8
            Wire.onReceive(receiveEvent);
             
          // Toggle motor depending on whether
          // button is pressed
          if (dp.isButtonPressed()) {
            startTime = millis();
            Serial.println("Dispensing.");
            dp.motorOn(255);
//            Wire.onReceive(receiveEvent);
           } else {
            dp.motorOff();
          }
          delay(5000);
       }

        // After timout, "stop dispensing",
        // and return to product screen
        dp.motorOff();
        dp.ledOff();
        dp.clearScreen();
        dp.showProductScreen();
      }
      delay(2500);
}
void receiveEvent(int howmany) {
  
  String weightstring = "";
  while(Wire.available()) // loop through all but the last
  {
    char w = Wire.read(); // receive byte as a character
    weightstring = weightstring + w;
    //Serial.print(weightstring);         // print the character
  }
   weight = weightstring.toFloat(); // respond with message of 6 bytes // as expected by master
   dp.showSaleScreen(weight);
   prevWeight = weight; 
  
}

The idea is to take the weight measured before the button is pressed and store it in a float type variable. Then after the button dispensing timeout is done, the weight is measured yet again and subtracted from the initial weight before the button is pressed to give the weight dispensed. The issue comes in retrieving the weight value on the Teensy 3.2 before the while loop. I am not sure how to initialize the Wire.begin( 8 ) / Wire.onReceive(receiveEvent) to execute the code appropriately and have it return to the beginning. Any insight on how to perform this would be very welcome. I have also attached my classes with the slave and master code below for reference. Thank you!View attachment Firmware_master.zip View attachment firmware_slave.zip
 
Look at File > Examples > Wire > slave_receiver for an example of using those functions.

The wire library also has a master_writer example which you can run on the other side to send data to Teensy. I'd recommend running these 2 very simple examples first, so you know the I2C communication works. Best to get that tested with the simple example code before throwing in the complexity of so much other stuff.
 
Look at File > Examples > Wire > slave_receiver for an example of using those functions.

The wire library also has a master_writer example which you can run on the other side to send data to Teensy. I'd recommend running these 2 very simple examples first, so you know the I2C communication works. Best to get that tested with the simple example code before throwing in the complexity of so much other stuff.

I have already tested the example code and was able to run a version of my project in it very well. As it stands, I am able to receive weight values from my master ESP32, my issue is that I can only appropriately do it when I plug Wire.begin() and Wire.onReceive() into the while loop in loop() as shown above. If I do not do this, my receiveEvent() function runs indefinitely and it prevents my Teensy 3.2 from returning back to the beginning of the loop to prompt for the RFID card.

Also, the way I require my display to function is to consistently update the screen values with new weight difference received from the master ESP32 I2C while my dispenser button is pressed and then return the final value after the button is done being pressed; even when the ESP32 is not connected to the button but my Teensy 3.2 is.

Component connections are as follows:

ESP32 Master:
- Load cell amplifier

Teensy 3.2 Slave:
-4.2 inch Waveshare e-paper display
-LED embedded antivandal push button
-MFRC522 RFID module
-Piezo buzzer
 
Status
Not open for further replies.
Back
Top