Skip to content

Instantly share code, notes, and snippets.

@cattaka

cattaka/CatWeight.ino

Last active Mar 3, 2020
Embed
What would you like to do?
#include <Arduino.h>
#include <M5Stack.h>
#include <WiFi.h>
#include <HTTPClient.h>
#define CYAN 0x07FF
#define ORANGE 0xFDA0
#define LIGHTGRAY 0xC618
#define FW 6
#define FH 8
void AE_HX711_Init(void);
void AE_HX711_Reset(void);
long AE_HX711_Read(void);
long AE_HX711_Averaging(long adc, char num);
float AE_HX711_getGram(char num);
//---------------------------------------------------//
// ピンの設定
//---------------------------------------------------//
#define pin_dout 17
#define pin_slk 16
#define OUT_VOL 0.0005f // 定格出力 [V]
#define LOAD 50000.0f // 定格容量 [g]
//---------------------------------------------------//
// ネットワーク
//---------------------------------------------------//
#define REQUEST_URL "https://script.google.com/macros/s/<<ここにキーが入る>>/exec?raw_weight_from=%.3f&raw_weight_to=%.3f&etc=%s"
const char SSID[] = "<<ここにWiFiのここにSSIDを入れる>>";
const char PASSWORD[] = "<<ここにWiFiのパスワードを入れる>>";
const char* rootCACertificate = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIESjCCAzKgAwIBAgINAeO0mqGNiqmBJWlQuDANBgkqhkiG9w0BAQsFADBMMSAw\n" \
"HgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFs\n" \
"U2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xNzA2MTUwMDAwNDJaFw0yMTEy\n" \
"MTUwMDAwNDJaMEIxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVHb29nbGUgVHJ1c3Qg\n" \
"U2VydmljZXMxEzARBgNVBAMTCkdUUyBDQSAxTzEwggEiMA0GCSqGSIb3DQEBAQUA\n" \
"A4IBDwAwggEKAoIBAQDQGM9F1IvN05zkQO9+tN1pIRvJzzyOTHW5DzEZhD2ePCnv\n" \
"UA0Qk28FgICfKqC9EksC4T2fWBYk/jCfC3R3VZMdS/dN4ZKCEPZRrAzDsiKUDzRr\n" \
"mBBJ5wudgzndIMYcLe/RGGFl5yODIKgjEv/SJH/UL+dEaltN11BmsK+eQmMF++Ac\n" \
"xGNhr59qM/9il71I2dN8FGfcddwuaej4bXhp0LcQBbjxMcI7JP0aM3T4I+DsaxmK\n" \
"FsbjzaTNC9uzpFlgOIg7rR25xoynUxv8vNmkq7zdPGHXkxWY7oG9j+JkRyBABk7X\n" \
"rJfoucBZEqFJJSPk7XA0LKW0Y3z5oz2D0c1tJKwHAgMBAAGjggEzMIIBLzAOBgNV\n" \
"HQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1Ud\n" \
"EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFJjR+G4Q68+b7GCfGJAboOt9Cf0rMB8G\n" \
"A1UdIwQYMBaAFJviB1dnHB7AagbeWbSaLd/cGYYuMDUGCCsGAQUFBwEBBCkwJzAl\n" \
"BggrBgEFBQcwAYYZaHR0cDovL29jc3AucGtpLmdvb2cvZ3NyMjAyBgNVHR8EKzAp\n" \
"MCegJaAjhiFodHRwOi8vY3JsLnBraS5nb29nL2dzcjIvZ3NyMi5jcmwwPwYDVR0g\n" \
"BDgwNjA0BgZngQwBAgIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly9wa2kuZ29vZy9y\n" \
"ZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAGoA+Nnn78y6pRjd9XlQWNa7H\n" \
"TgiZ/r3RNGkmUmYHPQq6Scti9PEajvwRT2iWTHQr02fesqOqBY2ETUwgZQ+lltoN\n" \
"FvhsO9tvBCOIazpswWC9aJ9xju4tWDQH8NVU6YZZ/XteDSGU9YzJqPjY8q3MDxrz\n" \
"mqepBCf5o8mw/wJ4a2G6xzUr6Fb6T8McDO22PLRL6u3M4Tzs3A2M1j6bykJYi8wW\n" \
"IRdAvKLWZu/axBVbzYmqmwkm5zLSDW5nIAJbELCQCZwMH56t2Dvqofxs6BBcCFIZ\n" \
"USpxu6x6td0V7SvJCCosirSmIatj/9dSSVDQibet8q/7UK4v4ZUN80atnZz1yg==\n" \
"-----END CERTIFICATE-----\n";
WiFiClientSecure client;
//---------------------------------------------------//
// コード本体
//---------------------------------------------------//
#define GET_GRAM_COUNT 5
#define RAW_DATA_BUF 6
#define MIN_DELAY_MSEC 500
#define VIRIANCE_THRESHOLD 0.005
#define SEND_THRESHOLD_KG 0.500
float gRawDataBuf[RAW_DATA_BUF];
int gRawDataBufPos = 0;
float gOffsetForDisplay;
unsigned long mLastMillis;
boolean gIsStabled = false;
float gLastStabledRawData = 0;
float gFromRawData = 0; // 送信用
float gToRawData = 0; // 送信用
boolean gShowDisplay = false;
boolean gRequireSend = false;
boolean gIsFirstSend = true;
void ensureWifi() {
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextSize(3);
M5.Lcd.setTextColor(LIGHTGRAY);
M5.Lcd.drawString("Ensuring WiFi...", 20, 100);
if (WiFi.waitForConnectResult() == WL_DISCONNECTED) {
M5.Lcd.setTextSize(2);
M5.Lcd.setTextColor(RED);
M5.Lcd.drawString("Failed! rebooting...", 20, 140);
delay(500);
esp_restart();
}
}
void setup() {
M5.begin(true, false, false, false);
WiFi.begin(SSID, PASSWORD);
ensureWifi();
M5.Lcd.setBrightness(0xFF);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextSize(2);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextDatum(TC_DATUM);
M5.Lcd.drawString("Initializing", 160, 100);
M5.Lcd.drawString("Press Button C", 160, 140);
client.setCACert(rootCACertificate);
Serial.begin(115200);
Serial.println("AE_HX711 test");
AE_HX711_Init();
Serial.println("Init done");
AE_HX711_Reset();
Serial.println("Reset done");
gOffsetForDisplay = 0;
for (int i=0;i<RAW_DATA_BUF;i++) {
gRawDataBuf[i] = AE_HX711_getGram(GET_GRAM_COUNT) / 1000;
gOffsetForDisplay += gRawDataBuf[i];
}
gOffsetForDisplay /= RAW_DATA_BUF;
Serial.println("AE_HX711_getGram");
mLastMillis = millis();
M5.Lcd.setBrightness(gShowDisplay ? 0xFF : 0x00);
}
void loop()
{
M5.update();
// Reset gOffset
if (M5.BtnA.wasReleased()) {
gOffsetForDisplay = gRawDataBuf[gRawDataBufPos];
}
if (M5.BtnB.wasReleased()) {
gRequireSend = true;
gFromRawData = gLastStabledRawData;
gToRawData = gLastStabledRawData;
}
if (M5.BtnC.wasReleased()) {
gShowDisplay = !gShowDisplay;
M5.Lcd.setBrightness(gShowDisplay ? 0xFF : 0x00);
}
// Get gram and save it into gRawDataBuf
float rawData = AE_HX711_getGram(GET_GRAM_COUNT) / 1000;
gRawDataBuf[gRawDataBufPos] = rawData;
gRawDataBufPos = (gRawDataBufPos + 1) % RAW_DATA_BUF;
// Calc average and variance
float avg = 0;
for (int i=0;i<RAW_DATA_BUF;i++) {
avg += gRawDataBuf[i];
}
avg /= RAW_DATA_BUF;
float variance = 0;
for (int i=0;i<RAW_DATA_BUF;i++) {
float v = gRawDataBuf[i] - avg;
variance += v * v;
}
variance /= RAW_DATA_BUF;
boolean isStabled = (variance < VIRIANCE_THRESHOLD);
if (gIsStabled != isStabled) {
if (isStabled) {
if (gIsFirstSend) {
gRequireSend = true;
gFromRawData = avg;
gToRawData = avg;
} else if (abs(avg - gFromRawData) > SEND_THRESHOLD_KG) {
gRequireSend = true;
gToRawData = avg;
}
} else {
gFromRawData = gLastStabledRawData;
}
gIsStabled = isStabled;
}
if (gIsStabled) {
gLastStabledRawData = avg;
}
// Display values
char buf[128];
Serial.printf("% 2.2f kg,(avg=% 2.2f kg, variance=% 2.4f)\n", rawData, avg, variance);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextSize(1);
M5.Lcd.setTextColor(LIGHTGRAY);
M5.Lcd.setTextDatum(TR_DATUM);
M5.Lcd.drawString(WiFi.localIP().toString(), 320, 0);
M5.Lcd.setTextDatum(TL_DATUM);
M5.Lcd.drawString("Set offset", 0,240 - FH);
M5.Lcd.setTextDatum(TC_DATUM);
M5.Lcd.drawString("Force send", 160, 240 - FH);
M5.Lcd.setTextDatum(TR_DATUM);
M5.Lcd.drawString("Display", 320,240 - FH);
M5.Lcd.setTextDatum(TL_DATUM);
M5.Lcd.setTextSize(2);
M5.Lcd.setTextColor(ORANGE);
M5.Lcd.drawString("Weight", FW * 2, FH * 0);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(4);
sprintf(buf, "% 2.2f kg", rawData - gOffsetForDisplay);
M5.Lcd.drawString(buf, FW * 6, FH * 4);
M5.Lcd.fillRect(FW * 0, FH * 4, FW * 4, FH * 4, gIsStabled ? BLUE : RED);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(4);
sprintf(buf, "% 2.2f kg", gFromRawData - gOffsetForDisplay);
M5.Lcd.drawString(buf, FW * 6, FH * 10);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(4);
sprintf(buf, "% 2.2f kg", gToRawData - gOffsetForDisplay);
M5.Lcd.drawString(buf, FW * 6, FH * 16);
M5.Lcd.fillRect(FW * 0, FH * 16, FW * 4, FH * 4, gRequireSend ? YELLOW : BLUE);
// Send request
if (gRequireSend && WiFi.status() == WL_CONNECTED) {
char url[256];
sprintf(url, REQUEST_URL, gFromRawData, gToRawData, gIsFirstSend ? "first_send" : "");
Serial.println(url);
for (int i=0;i<3;i++) {
HTTPClient https;
if (https.begin(client, url)) {
Serial.println("begin succeed");
int statusCode = https.GET();
if (200 <= statusCode && statusCode < 300) {
}
gIsFirstSend = false;
gRequireSend = false;
Serial.println(statusCode, DEC);
https.end();
break;
} else {
Serial.println("begin failed");
https.end();
}
}
}
// Wait delays
unsigned long ct = millis();
long frameMsec = (long)(ct - mLastMillis);
if (0 < frameMsec && frameMsec < MIN_DELAY_MSEC) {
delay(MIN_DELAY_MSEC - frameMsec);
}
}
void AE_HX711_Init(void)
{
pinMode(pin_slk, OUTPUT);
pinMode(pin_dout, INPUT);
}
void AE_HX711_Reset(void)
{
digitalWrite(pin_slk, 1);
delayMicroseconds(100);
digitalWrite(pin_slk, 0);
delayMicroseconds(100);
}
long AE_HX711_Read(void)
{
long data = 0;
while (digitalRead(pin_dout) != 0);
delayMicroseconds(10);
for (int i = 0; i < 24; i++)
{
digitalWrite(pin_slk, 1);
delayMicroseconds(5);
digitalWrite(pin_slk, 0);
delayMicroseconds(5);
data = (data << 1) | (digitalRead(pin_dout));
}
//Serial.println(data,HEX);
digitalWrite(pin_slk, 1);
delayMicroseconds(10);
digitalWrite(pin_slk, 0);
delayMicroseconds(10);
return data ^ 0x800000;
}
long AE_HX711_Averaging(long adc, char num)
{
long sum = 0;
for (int i = 0; i < num; i++) sum += AE_HX711_Read();
return sum / num;
}
float AE_HX711_getGram(char num)
{
#define HX711_R1 20000.0f
#define HX711_R2 8200.0f
#define HX711_VBG 1.25f
#define HX711_AVDD 4.2987f//(HX711_VBG*((HX711_R1+HX711_R2)/HX711_R2))
#define HX711_ADC1bit HX711_AVDD/16777216 //16777216=(2^24)
#define HX711_PGA 128
#define HX711_SCALE (OUT_VOL * HX711_AVDD / LOAD *HX711_PGA)
float data;
data = AE_HX711_Averaging(AE_HX711_Read(), num) * HX711_ADC1bit;
//Serial.println( HX711_AVDD);
//Serial.println( HX711_ADC1bit);
//Serial.println( HX711_SCALE);
//Serial.println( data);
data = data / HX711_SCALE;
return data;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.