Roller Mill Remote Scale Display
2021-07-10 | By M5Stack
License: General Public License Arduino
* Thanks for the source code and project information provided by @Eathan Rethmeier
Goal
This project came about after pricing commercially available remote displays for our roller mill. We wanted a display at the front of the mill so that the operator could see the weights from the both the tractor seat and be large and easy to read in the dark.
Reasoning
Displays that are available and compatible for our scales were more expensive than we really wanted to pay. I decided to use my limited programming knowledge and the experiences I have had with microcontrollers in past projects to come up with a solution.
Hardware
I decided to base the project around the ESP32 module. I specifically chose the M5Stack Atom RS232 because I had used the Atom module before in a different project with good success. I also used 7 of m5Stack's SK6812 Digital RGB LED Strips. The 20cm version was long enough to represent the number of characters I needed.
Communication
The scale on the mill had a serial port which made it an obvious mode of communication. The physical connection was a little tricky because the form factor of the port was not a DB9 or something similar, but was an 8 pin AMP connector. A little digging through the scale's manufacturing literature did give a pinout for the connector and a little trial and error led to successfully isolating TX/RX pins and ground (yes, a little "magic smoke" was released). For my purposes, I only used the RX and ground pins.
Power
Power was supplied from the 12-volt accessory outlet that is common on most agricultural equipment. I did not directly power the Atom RS232 using the provided pins on that unit, but instead opted to use a separate power converter to go from 12 volt to 5 volt and power the Atom through the USB. The number of LED Strips used was not enough to over tax the Atom's ability to supply power through the Grove port. I was careful to limit power draw by only turning on the LEDs I needed and lowering the brightness of the strips. Any version of this kind of display that is larger I would recommend using a second power converter to supply the LED strips. Also running the WIFI or the Bluetooth in the Atom will contribute to power draw (for the sake of simplicity I disabled both).
Physical Construction
The box is constructed with PVC board, Plexiglass and stainless-steel screws. The box is glued together with super glue and reinforced with screws. The Plexiglass has sealant to on the top and sides, but not the bottom to allow air exchange and unwanted moisture to dissipate. The LED strip are connected in a series that is zigzagged in the display. This is important to note because your sketch setup requires this information to properly display data to the LED strips.
Schematics
In Progress
Software
I used the Arduino IDE with ESP32 plugin. Hunting down the correct libraries was mildly difficult and required extensive Google use (mostly ended being Adafruit based libraries). But basically, the current sketch can be boiled down to doing two things: parsing the serial data and instructing the LED strips in matrix in a loop. Parsing the serial data was simply retrieving any whole integers in the stream. This method may not work depending on how different scales outputs data.
Please forgive the readability of the sketch. I am mostly a novice playing with fire and a keyboard. ALL software is as is and all outcomes are not guaranteed.
Future changes
The next versions of this display will have dual power supplies so that larger LED strips can be used as well as the WIFI portion of the Atom. Also running a websocket server on the atom to allow customization of display (i.e. color, brightness, special modes and units of measure if applicable) from any web browser.
//5_14_2021
//Smart Scale
//todo list
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#include "M5Atom.h"
// Fields
uint8_t res;
//const char* ssid = "";
//const char* password = "";
//const char* hostname = "";
//const byte DNS_PORT = 53;
//IPAddress apIP( 192, 168, 4, 1 );
//DNSServer dnsServer;
//User defined stored data
int Scale_Type = 1;
int Scale_Color = 0;
String ch = "";
//neopixel pin designation
#define PIN 26
// MATRIX DECLARATION:
// Parameter 1 = width of NeoPixel matrix
// Parameter 2 = height of matrix
// Parameter 3 = pin number (most are valid)
// Parameter 4 = matrix layout flags, add together as needed:
// NEO_MATRIX_TOP, NEO_MATRIX_BOTTOM, NEO_MATRIX_LEFT, NEO_MATRIX_RIGHT:
// Position of the FIRST LED in the matrix; pick two, e.g.
// NEO_MATRIX_TOP + NEO_MATRIX_LEFT for the top-left corner.
// NEO_MATRIX_ROWS, NEO_MATRIX_COLUMNS: LEDs are arranged in horizontal
// rows or in vertical columns, respectively; pick one or the other.
// NEO_MATRIX_PROGRESSIVE, NEO_MATRIX_ZIGZAG: all rows/columns proceed
// in the same order, or alternate lines reverse direction; pick one.
// See example below for these values in action.
// Parameter 5 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_GRBW Pixels are wired for GRBW bitstream (RGB+W NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// Example for NeoPixel Shield. In this application we'd like to use it
// as a 5x8 tall matrix, with the USB port positioned at the top of the
// Arduino. When held that way, the first pixel is at the top right, and
// lines are arranged in columns, progressive order. The shield uses
// 800 KHz (v2) pixels that expect GRB color data.
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(29, 8, PIN,
NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
NEO_RGB + NEO_KHZ800);
const uint16_t colors[] = {
matrix.Color(255, 0, 0), matrix.Color(0, 255, 0), matrix.Color(0, 255, 0) };
//uint16_t Serial_Output;
void setup() {
M5.begin();
// Serial2.begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert)
Serial2.begin(9600, SERIAL_8N1, 22, 19);
//Serial2.begin(9600, 22, 19);
//
// #if defined(ESP32)
// WiFi.setHostname( hostname );
//#else
// WiFi.hostname( hostname );
//#endif
//
// // try to connect to existing network
// WiFi.begin( ssid, password );
// Serial.print(F( "\n\nTry to connect to existing network") );
//
// {
// uint8_t timeout = 20;
//
// // Wait for connection, 5s timeout
// do {
// delay( 500 );
// Serial.print( "." );
// timeout--;
// } while ( timeout && WiFi.status() != WL_CONNECTED );
//
// // not connected -> create hotspot
// if ( WiFi.status() != WL_CONNECTED ) {
// Serial.print( F("\n\nCreating hotspot") );
//
// WiFi.mode( WIFI_AP );
// WiFi.softAPConfig( apIP, apIP, IPAddress( 255, 255, 255, 0 ) );
// WiFi.softAP( "ScaleDisplay");
//
// timeout = 5;
//
// do {
// delay( 500 );
// Serial.print( "." );
// timeout--;
// } while ( timeout );
// }
// }
//
// dnsServer.start( DNS_PORT, "*", apIP );
//
// /////
// Serial.println( "\n\nWiFi parameters:" );
// Serial.print( "Mode: " );
// Serial.println( WiFi.getMode() == WIFI_AP ? "Station" : "Client" );
// Serial.print( "IP address: " );
// Serial.println( WiFi.getMode() == WIFI_AP ? WiFi.softAPIP() : WiFi.localIP() );
//
//
// uint16_t tab1 = ESPUI.addControl( ControlType::Tab, "Settings 1", "Scale" );
// uint16_t tab2 = ESPUI.addControl( ControlType::Tab, "Settings 2", "Settings" );
//
//Serial_Output =ESPUI.addControl( ControlType::Label, "Scale", "", ControlColor::Turquoise, tab1 );
//
//
//
// ESPUI.begin("Scale");
// // put your setup code here, to run once:
//matrix.setTextColor(matrix.Color(7,0,0));
matrix.setBrightness(64);
}
//
int x= matrix.width();
int pass = 0;
//
void loop() {
// put your main code here, to run repeatedly:
//dnsServer.processNextRequest();
if(Serial2.available()) {
{
//ch = Serial2.readStringUntil((''));
ch = Serial2.parseInt();
//ch.trim();
// Serial.print(ch);
// Serial.flush();
// ESPUI.updateControlValue(Serial_Output, ch);
//M5.dis.drawpix(0, 0x00ffff);
M5.update();
delay(50);
//LED Matrix update
matrix.fillScreen(0);
matrix.setCursor(0, 0);
matrix.setTextColor(colors[pass]);
matrix.print(ch);
matrix.show();
delay(100);
}
}
}
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum