// toilet paper sheet counter
// vgmlr
#include "LiquidCrystal.h"
#include "ESP8266WiFi.h"
#include "MapFloat.h"
// display
LiquidCrystal lcd(D6, D5, D4, D3, D2, D1);
// sensor
const int hall = D7;
int hs, hn;
// button
const int b_left = D0;
const int b_right = D8;
int bl, br;
// states
int new_roll, total_sheets, sheets_left;
int pull_now, last_pull, pull_total;
long pull_value, passed;
long hold = 300000; // 5 minutes
// wifi
const char* ssid = "yourssid";
const char* password = "yourpass";
WiFiServer server(80);
// thingspeak
char thingSpeakAddress[] = "api.thingspeak.com";
String APIKey = "yourapikey"; // API
const int updateThingSpeakInterval = 10 * 1000;
long lastConnectionTime = 0;
boolean lastConnected = false;
WiFiClient client;
void setup() {
Serial.begin(115200);
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("Toilet Paper");
lcd.setCursor(0, 1);
lcd.print("Sheet Counter");
delay(1500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connecting...");
while (WiFi.status() != WL_CONNECTED) {
WiFi.begin(ssid, password);
delay(10000);
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connected");
server.begin();
delay(1000);
lcd.clear();
pinMode(b_left, INPUT);
pinMode(b_right, INPUT);
pinMode(hall, INPUT);
}
void loop() {
// new roll setting
if (new_roll == 0) {
select_roll();
}
// read roll
hs = digitalRead(hall);
if (hs == LOW) {
// to isolate requests
if (hn == 0) {
// spiral maths
pull_value = mapFloat(pull_total, 0, total_sheets, 2.25, 0.5);
pull_value = round(pull_value); // this ruins it
pull_now = pull_now + pull_value;
pull_total = pull_total + pull_value;
sheets_left = total_sheets - pull_total;
update_display();
// states
passed = 0;
hn = 1;
}
} else {
hn = 0;
}
// dont count time if inactive
if (pull_now != 0) {
passed++;
Serial.println(passed);
}
// send and reset
if (passed > hold) {
net_send();
last_pull = pull_now;
pull_now = 0;
passed = 0;
lcd.setCursor(5, 0);
lcd.print(" ");
lcd.setCursor(5, 1);
lcd.print(" ");
update_display();
}
// end of roll
if (sheets_left < 1) {
new_roll = 0;
}
// reset roll button
br = digitalRead(b_right);
if (br == HIGH) {
new_roll = 0;
delay(700);
}
}
void select_roll() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Sheets");
total_sheets = 200;
while (digitalRead(b_right) == LOW) {
lcd.setCursor(0, 1);
lcd.print(total_sheets);
bl = digitalRead(b_left);
if (bl == HIGH) {
total_sheets = total_sheets + 5;
delay(100);
}
yield(); // esp fix
}
last_pull = 0;
pull_total = 0;
pull_now = 0;
sheets_left = total_sheets;
new_roll = 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Last");
lcd.setCursor(5, 0);
lcd.print(last_pull);
lcd.setCursor(10, 0);
lcd.print("(+");
lcd.setCursor(12, 0);
lcd.print(pull_total);
lcd.setCursor(15, 0);
lcd.print(")");
lcd.setCursor(0, 1);
lcd.print("Now");
lcd.setCursor(5, 1);
lcd.print(pull_now);
lcd.setCursor(10, 1);
lcd.print("(-");
lcd.setCursor(12, 1);
lcd.print(sheets_left);
lcd.setCursor(15, 1);
lcd.print(")");
delay(500);
}
void update_display() {
lcd.setCursor(5, 0);
lcd.print(last_pull);
lcd.setCursor(12, 0);
lcd.print(pull_total);
lcd.setCursor(5, 1);
lcd.print(pull_now);
lcd.setCursor(12, 1);
lcd.print(sheets_left);
}
void net_send() {
String last_sheet = String(pull_now, DEC);
String last_total = String(pull_total, DEC);
updateThingSpeak("field1=" + last_sheet + "&field2=" + last_total);
delay(3000);
}
void updateThingSpeak(String tsData) {
if (client.connect(thingSpeakAddress, 80)) {
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: " + APIKey + "\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(tsData.length());
client.print("\n\n");
client.print(tsData);
}
}