Menu
Index
Engineering
Entertainment
Literature
Miscellaneous
Contact
Search
tiktok.com/@pkvi.xyz
buymeacoffee.com/pkvi
scored.co/u/pkvi_halfkdeltaxsq
Miter
Why Ayh?
Miter
@pkvi
"...may not meet professional standards."
772 miters
122 tenons
Subscribe
0.00394
NodeMCU WiFi Toilet Paper Sheet Counter


NodeMCU
Hall Sensor Module
Neodymium Magnets (2)
16X2 LCD Display
Momentary Buttons (2)
10K Resistor (2)
1K Resistor (1)
10K Potentiometer
USB Female Module
5V 2A Power Supply



  1. // toilet paper sheet counter
  2. // pkvi
  3. #include <LiquidCrystal.h>
  4. #include <ESP8266WiFi.h>
  5. #include "MapFloat.h"
  6. // display
  7. LiquidCrystal lcd(D6, D5, D4, D3, D2, D1);
  8. // sensor
  9. const int hall = D7;
  10. int hs, hn;
  11. // button
  12. const int b_left = D0;
  13. const int b_right = D8;
  14. int bl, br;
  15. // states
  16. int new_roll, total_sheets, sheets_left;
  17. int pull_now, last_pull, pull_total;
  18. long pull_value, passed;
  19. long hold = 300000; // 5 minutes
  20. // wifi
  21. const char* ssid = "yourssid";
  22. const char* password = "yourpass";
  23. WiFiServer server(80);
  24. // thingspeak
  25. char thingSpeakAddress[] = "api.thingspeak.com";
  26. String APIKey = "yourapikey"; // API
  27. const int updateThingSpeakInterval = 10 * 1000;
  28. long lastConnectionTime = 0;
  29. boolean lastConnected = false;
  30. WiFiClient client;
  31. void setup() {
  32. Serial.begin(115200);
  33. lcd.begin(16, 2);
  34. lcd.setCursor(0, 0);
  35. lcd.print("Toilet Paper");
  36. lcd.setCursor(0, 1);
  37. lcd.print("Sheet Counter");
  38. delay(1500);
  39. lcd.clear();
  40. lcd.setCursor(0, 0);
  41. lcd.print("Connecting...");
  42. while (WiFi.status() != WL_CONNECTED) {
  43. WiFi.begin(ssid, password);
  44. delay(10000);
  45. }
  46. lcd.clear();
  47. lcd.setCursor(0, 0);
  48. lcd.print("Connected");
  49. server.begin();
  50. delay(1000);
  51. lcd.clear();
  52. pinMode(b_left, INPUT);
  53. pinMode(b_right, INPUT);
  54. pinMode(hall, INPUT);
  55. }
  56. void loop() {
  57. // new roll setting
  58. if (new_roll == 0) {
  59. select_roll();
  60. }
  61. // read roll
  62. hs = digitalRead(hall);
  63. if (hs == LOW) {
  64. // to isolate requests
  65. if (hn == 0) {
  66. // spiral maths
  67. pull_value = mapFloat(pull_total, 0, total_sheets, 2.25, 0.5);
  68. pull_value = round(pull_value); // this ruins it
  69. pull_now = pull_now + pull_value;
  70. pull_total = pull_total + pull_value;
  71. sheets_left = total_sheets - pull_total;
  72. update_display();
  73. // states
  74. passed = 0;
  75. hn = 1;
  76. }
  77. } else {
  78. hn = 0;
  79. }
  80. // dont count time if inactive
  81. if (pull_now != 0) {
  82. passed++;
  83. Serial.println(passed);
  84. }
  85. // send and reset
  86. if (passed > hold) {
  87. net_send();
  88. last_pull = pull_now;
  89. pull_now = 0;
  90. passed = 0;
  91. lcd.setCursor(5, 0);
  92. lcd.print(" ");
  93. lcd.setCursor(5, 1);
  94. lcd.print(" ");
  95. update_display();
  96. }
  97. // end of roll
  98. if (sheets_left < 1) {
  99. new_roll = 0;
  100. }
  101. // reset roll button
  102. br = digitalRead(b_right);
  103. if (br == HIGH) {
  104. new_roll = 0;
  105. delay(700);
  106. }
  107. }
  108. void select_roll() {
  109. lcd.clear();
  110. lcd.setCursor(0, 0);
  111. lcd.print("Select Sheets");
  112. total_sheets = 200;
  113. while (digitalRead(b_right) == LOW) {
  114. lcd.setCursor(0, 1);
  115. lcd.print(total_sheets);
  116. bl = digitalRead(b_left);
  117. if (bl == HIGH) {
  118. total_sheets = total_sheets + 5;
  119. delay(100);
  120. }
  121. yield(); // esp fix
  122. }
  123. last_pull = 0;
  124. pull_total = 0;
  125. pull_now = 0;
  126. sheets_left = total_sheets;
  127. new_roll = 1;
  128. lcd.clear();
  129. lcd.setCursor(0, 0);
  130. lcd.print("Last");
  131. lcd.setCursor(5, 0);
  132. lcd.print(last_pull);
  133. lcd.setCursor(10, 0);
  134. lcd.print("(+");
  135. lcd.setCursor(12, 0);
  136. lcd.print(pull_total);
  137. lcd.setCursor(15, 0);
  138. lcd.print(")");
  139. lcd.setCursor(0, 1);
  140. lcd.print("Now");
  141. lcd.setCursor(5, 1);
  142. lcd.print(pull_now);
  143. lcd.setCursor(10, 1);
  144. lcd.print("(-");
  145. lcd.setCursor(12, 1);
  146. lcd.print(sheets_left);
  147. lcd.setCursor(15, 1);
  148. lcd.print(")");
  149. delay(500);
  150. }
  151. void update_display() {
  152. lcd.setCursor(5, 0);
  153. lcd.print(last_pull);
  154. lcd.setCursor(12, 0);
  155. lcd.print(pull_total);
  156. lcd.setCursor(5, 1);
  157. lcd.print(pull_now);
  158. lcd.setCursor(12, 1);
  159. lcd.print(sheets_left);
  160. }
  161. void net_send() {
  162. String last_sheet = String(pull_now, DEC);
  163. String last_total = String(pull_total, DEC);
  164. updateThingSpeak("field1=" + last_sheet + "&field2=" + last_total);
  165. delay(3000);
  166. }
  167. void updateThingSpeak(String tsData) {
  168. if (client.connect(thingSpeakAddress, 80)) {
  169. client.print("POST /update HTTP/1.1\n");
  170. client.print("Host: api.thingspeak.com\n");
  171. client.print("Connection: close\n");
  172. client.print("X-THINGSPEAKAPIKEY: " + APIKey + "\n");
  173. client.print("Content-Type: application/x-www-form-urlencoded\n");
  174. client.print("Content-Length: ");
  175. client.print(tsData.length());
  176. client.print("\n\n");
  177. client.print(tsData);
  178. }
  179. }