
Test
Dependencies: mbed Adafruit_GFX DS1307
main.cpp@0:4ee8e6f5f993, 2019-06-01 (annotated)
- Committer:
- VinPer
- Date:
- Sat Jun 01 14:47:54 2019 +0000
- Revision:
- 0:4ee8e6f5f993
bla
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
VinPer | 0:4ee8e6f5f993 | 1 | #include "mbed.h" |
VinPer | 0:4ee8e6f5f993 | 2 | #include "Adafruit_SSD1306.h" |
VinPer | 0:4ee8e6f5f993 | 3 | #include <string> |
VinPer | 0:4ee8e6f5f993 | 4 | #include <sstream> |
VinPer | 0:4ee8e6f5f993 | 5 | |
VinPer | 0:4ee8e6f5f993 | 6 | void Rx_interrupt(); |
VinPer | 0:4ee8e6f5f993 | 7 | void writeStringToOLED(string str, int x, int y); |
VinPer | 0:4ee8e6f5f993 | 8 | void showStatus(); |
VinPer | 0:4ee8e6f5f993 | 9 | void toggleLED(); |
VinPer | 0:4ee8e6f5f993 | 10 | void waterPlant(); |
VinPer | 0:4ee8e6f5f993 | 11 | void waterCritical(); |
VinPer | 0:4ee8e6f5f993 | 12 | |
VinPer | 0:4ee8e6f5f993 | 13 | void drawSmile(); |
VinPer | 0:4ee8e6f5f993 | 14 | void drawIdle(); |
VinPer | 0:4ee8e6f5f993 | 15 | void drawSleep(); |
VinPer | 0:4ee8e6f5f993 | 16 | void drawDead(); |
VinPer | 0:4ee8e6f5f993 | 17 | |
VinPer | 0:4ee8e6f5f993 | 18 | volatile bool sleepCycle; |
VinPer | 0:4ee8e6f5f993 | 19 | |
VinPer | 0:4ee8e6f5f993 | 20 | /* |
VinPer | 0:4ee8e6f5f993 | 21 | OLED |
VinPer | 0:4ee8e6f5f993 | 22 | P5 -> MOSI |
VinPer | 0:4ee8e6f5f993 | 23 | P6 -> aberto |
VinPer | 0:4ee8e6f5f993 | 24 | P7 -> CLK |
VinPer | 0:4ee8e6f5f993 | 25 | Pinos variáveis |
VinPer | 0:4ee8e6f5f993 | 26 | P8 -> RES |
VinPer | 0:4ee8e6f5f993 | 27 | P9 -> DC |
VinPer | 0:4ee8e6f5f993 | 28 | P10 -> CS |
VinPer | 0:4ee8e6f5f993 | 29 | |
VinPer | 0:4ee8e6f5f993 | 30 | Configuração SPI entra com (MOSI, MISO, CLK) |
VinPer | 0:4ee8e6f5f993 | 31 | Configuração OLED entra com (SPI, DC, RES, CS, altura, largura) |
VinPer | 0:4ee8e6f5f993 | 32 | */ |
VinPer | 0:4ee8e6f5f993 | 33 | SPI spi(p5, p6, p7); |
VinPer | 0:4ee8e6f5f993 | 34 | Adafruit_SSD1306_Spi spiOLED(spi, p9, p8, p10, 32, 128); |
VinPer | 0:4ee8e6f5f993 | 35 | |
VinPer | 0:4ee8e6f5f993 | 36 | /* |
VinPer | 0:4ee8e6f5f993 | 37 | BLUETOOTH |
VinPer | 0:4ee8e6f5f993 | 38 | P13 -> TX |
VinPer | 0:4ee8e6f5f993 | 39 | P14 -> RX |
VinPer | 0:4ee8e6f5f993 | 40 | |
VinPer | 0:4ee8e6f5f993 | 41 | Configuração serial entra com (RX, TX) |
VinPer | 0:4ee8e6f5f993 | 42 | */ |
VinPer | 0:4ee8e6f5f993 | 43 | |
VinPer | 0:4ee8e6f5f993 | 44 | |
VinPer | 0:4ee8e6f5f993 | 45 | Serial hc(p14, p13); |
VinPer | 0:4ee8e6f5f993 | 46 | |
VinPer | 0:4ee8e6f5f993 | 47 | /* |
VinPer | 0:4ee8e6f5f993 | 48 | Componentes que utilizam leitura análogica: |
VinPer | 0:4ee8e6f5f993 | 49 | P15 a P20 |
VinPer | 0:4ee8e6f5f993 | 50 | */ |
VinPer | 0:4ee8e6f5f993 | 51 | AnalogIn ldr(p15); |
VinPer | 0:4ee8e6f5f993 | 52 | AnalogIn hygroEarth(p16); |
VinPer | 0:4ee8e6f5f993 | 53 | AnalogIn hygroWater(p17); |
VinPer | 0:4ee8e6f5f993 | 54 | |
VinPer | 0:4ee8e6f5f993 | 55 | /* |
VinPer | 0:4ee8e6f5f993 | 56 | Componentes que utilizam leitura digital: |
VinPer | 0:4ee8e6f5f993 | 57 | Qualquer pino livre (P5 a P30) |
VinPer | 0:4ee8e6f5f993 | 58 | */ |
VinPer | 0:4ee8e6f5f993 | 59 | DigitalIn pres(p30); |
VinPer | 0:4ee8e6f5f993 | 60 | |
VinPer | 0:4ee8e6f5f993 | 61 | volatile bool ledStatus; |
VinPer | 0:4ee8e6f5f993 | 62 | volatile float waterLimit; |
VinPer | 0:4ee8e6f5f993 | 63 | volatile time_t seconds; |
VinPer | 0:4ee8e6f5f993 | 64 | |
VinPer | 0:4ee8e6f5f993 | 65 | int main() |
VinPer | 0:4ee8e6f5f993 | 66 | { |
VinPer | 0:4ee8e6f5f993 | 67 | set_time(0); |
VinPer | 0:4ee8e6f5f993 | 68 | seconds = time(NULL); |
VinPer | 0:4ee8e6f5f993 | 69 | // Resetar display |
VinPer | 0:4ee8e6f5f993 | 70 | spiOLED.clearDisplay(); |
VinPer | 0:4ee8e6f5f993 | 71 | drawSmile(); |
VinPer | 0:4ee8e6f5f993 | 72 | spiOLED.display(); |
VinPer | 0:4ee8e6f5f993 | 73 | wait(10); |
VinPer | 0:4ee8e6f5f993 | 74 | drawIdle(); |
VinPer | 0:4ee8e6f5f993 | 75 | |
VinPer | 0:4ee8e6f5f993 | 76 | ledStatus = false; |
VinPer | 0:4ee8e6f5f993 | 77 | sleepCycle = false; |
VinPer | 0:4ee8e6f5f993 | 78 | |
VinPer | 0:4ee8e6f5f993 | 79 | int tsEarth = 0; // |
VinPer | 0:4ee8e6f5f993 | 80 | int tsLight = 0; // |
VinPer | 0:4ee8e6f5f993 | 81 | int tsPres = 0; // |
VinPer | 0:4ee8e6f5f993 | 82 | |
VinPer | 0:4ee8e6f5f993 | 83 | int delayEarth = 3600; // |
VinPer | 0:4ee8e6f5f993 | 84 | int delayLight; // |
VinPer | 0:4ee8e6f5f993 | 85 | int delayPres = 7200; // |
VinPer | 0:4ee8e6f5f993 | 86 | |
VinPer | 0:4ee8e6f5f993 | 87 | waterLimit = 1; |
VinPer | 0:4ee8e6f5f993 | 88 | float lightLimit = 1; // |
VinPer | 0:4ee8e6f5f993 | 89 | float earthLimit = 1; // |
VinPer | 0:4ee8e6f5f993 | 90 | |
VinPer | 0:4ee8e6f5f993 | 91 | bool turnOnLED; |
VinPer | 0:4ee8e6f5f993 | 92 | bool turnOffLED; |
VinPer | 0:4ee8e6f5f993 | 93 | |
VinPer | 0:4ee8e6f5f993 | 94 | while(1){ |
VinPer | 0:4ee8e6f5f993 | 95 | seconds = time(NULL); |
VinPer | 0:4ee8e6f5f993 | 96 | |
VinPer | 0:4ee8e6f5f993 | 97 | /* |
VinPer | 0:4ee8e6f5f993 | 98 | HIGRÔMETRO TERRA |
VinPer | 0:4ee8e6f5f993 | 99 | - Rega a planta quando o nível de umidade detectado for adequado |
VinPer | 0:4ee8e6f5f993 | 100 | - Não rega se não tiver passado um determinado tempo desde a ultima vez |
VinPer | 0:4ee8e6f5f993 | 101 | |
VinPer | 0:4ee8e6f5f993 | 102 | Condição 1: Valor lido no higrômetro da terra maior (mais seco) que o limite |
VinPer | 0:4ee8e6f5f993 | 103 | Condição 2: Tempo desde a ultima vez que foi regado maior que o delay mínimo |
VinPer | 0:4ee8e6f5f993 | 104 | */ |
VinPer | 0:4ee8e6f5f993 | 105 | if (hygroEarth.read() > earthLimit && seconds - tsEarth > delayEarth) { |
VinPer | 0:4ee8e6f5f993 | 106 | tsEarth = seconds; |
VinPer | 0:4ee8e6f5f993 | 107 | waterPlant(); |
VinPer | 0:4ee8e6f5f993 | 108 | } |
VinPer | 0:4ee8e6f5f993 | 109 | |
VinPer | 0:4ee8e6f5f993 | 110 | /* |
VinPer | 0:4ee8e6f5f993 | 111 | SENSOR LDR E FITA DE LED |
VinPer | 0:4ee8e6f5f993 | 112 | - Liga/desliga a fita de LED dependendo do nível de luz |
VinPer | 0:4ee8e6f5f993 | 113 | (acrescentar: do horário do dia) |
VinPer | 0:4ee8e6f5f993 | 114 | |
VinPer | 0:4ee8e6f5f993 | 115 | Condição 1: Valor lido no LDR inferior a luz necessária |
VinPer | 0:4ee8e6f5f993 | 116 | Condição 2: LED está desligado |
VinPer | 0:4ee8e6f5f993 | 117 | Condição 3 (acrescentar): horário atual não ser noite |
VinPer | 0:4ee8e6f5f993 | 118 | */ |
VinPer | 0:4ee8e6f5f993 | 119 | turnOnLED = ldr.read() < lightLimit && !ledStatus; |
VinPer | 0:4ee8e6f5f993 | 120 | // Mesmas condições, mas inversas para desligar |
VinPer | 0:4ee8e6f5f993 | 121 | turnOffLED = ldr.read() > lightLimit && ledStatus; |
VinPer | 0:4ee8e6f5f993 | 122 | if (turnOnLED || turnOffLED) { |
VinPer | 0:4ee8e6f5f993 | 123 | toggleLED(); |
VinPer | 0:4ee8e6f5f993 | 124 | } |
VinPer | 0:4ee8e6f5f993 | 125 | |
VinPer | 0:4ee8e6f5f993 | 126 | /* |
VinPer | 0:4ee8e6f5f993 | 127 | SENSOR PRESENÇA |
VinPer | 0:4ee8e6f5f993 | 128 | - Desenha uma carinha feliz quando detecta presença de alguém ^u^ |
VinPer | 0:4ee8e6f5f993 | 129 | |
VinPer | 0:4ee8e6f5f993 | 130 | Condição 1: Valor lido no sensor de presença é 1 |
VinPer | 0:4ee8e6f5f993 | 131 | Condição 2: Tempo desde a ultima vez que foi ativado maior que o delay mínimo |
VinPer | 0:4ee8e6f5f993 | 132 | */ |
VinPer | 0:4ee8e6f5f993 | 133 | if (pres.read() && seconds - tsPres > delayPres) { |
VinPer | 0:4ee8e6f5f993 | 134 | tsPres = seconds; |
VinPer | 0:4ee8e6f5f993 | 135 | drawSmile(); |
VinPer | 0:4ee8e6f5f993 | 136 | wait(15); |
VinPer | 0:4ee8e6f5f993 | 137 | } |
VinPer | 0:4ee8e6f5f993 | 138 | |
VinPer | 0:4ee8e6f5f993 | 139 | /* |
VinPer | 0:4ee8e6f5f993 | 140 | HIGRÔMETRO ÁGUA |
VinPer | 0:4ee8e6f5f993 | 141 | - Interrompe o programa no caso de não ter água no tanque |
VinPer | 0:4ee8e6f5f993 | 142 | |
VinPer | 0:4ee8e6f5f993 | 143 | Condição 1: Valor lido no higrômetro da água maior (mais seco) que o limite |
VinPer | 0:4ee8e6f5f993 | 144 | */ |
VinPer | 0:4ee8e6f5f993 | 145 | if (hygroWater.read() > waterLimit) { |
VinPer | 0:4ee8e6f5f993 | 146 | waterCritical(); |
VinPer | 0:4ee8e6f5f993 | 147 | } |
VinPer | 0:4ee8e6f5f993 | 148 | |
VinPer | 0:4ee8e6f5f993 | 149 | /* |
VinPer | 0:4ee8e6f5f993 | 150 | DORMIR |
VinPer | 0:4ee8e6f5f993 | 151 | - O vaso dorme quando o horário for de noite. |
VinPer | 0:4ee8e6f5f993 | 152 | |
VinPer | 0:4ee8e6f5f993 | 153 | Condição 1: ??? horas noturnas |
VinPer | 0:4ee8e6f5f993 | 154 | */ |
VinPer | 0:4ee8e6f5f993 | 155 | |
VinPer | 0:4ee8e6f5f993 | 156 | // ... |
VinPer | 0:4ee8e6f5f993 | 157 | if (true) { |
VinPer | 0:4ee8e6f5f993 | 158 | drawSleep(); |
VinPer | 0:4ee8e6f5f993 | 159 | } |
VinPer | 0:4ee8e6f5f993 | 160 | |
VinPer | 0:4ee8e6f5f993 | 161 | wait(1); |
VinPer | 0:4ee8e6f5f993 | 162 | } |
VinPer | 0:4ee8e6f5f993 | 163 | } |
VinPer | 0:4ee8e6f5f993 | 164 | |
VinPer | 0:4ee8e6f5f993 | 165 | // Receber comandos manuais por bluetooth |
VinPer | 0:4ee8e6f5f993 | 166 | void Rx_interrupt() { |
VinPer | 0:4ee8e6f5f993 | 167 | char c; |
VinPer | 0:4ee8e6f5f993 | 168 | c = hc.getc(); |
VinPer | 0:4ee8e6f5f993 | 169 | switch(c){ |
VinPer | 0:4ee8e6f5f993 | 170 | case 'S': |
VinPer | 0:4ee8e6f5f993 | 171 | showStatus(); |
VinPer | 0:4ee8e6f5f993 | 172 | break; |
VinPer | 0:4ee8e6f5f993 | 173 | case 'A': |
VinPer | 0:4ee8e6f5f993 | 174 | waterPlant(); |
VinPer | 0:4ee8e6f5f993 | 175 | break; |
VinPer | 0:4ee8e6f5f993 | 176 | case 'L': |
VinPer | 0:4ee8e6f5f993 | 177 | toggleLED(); |
VinPer | 0:4ee8e6f5f993 | 178 | break; |
VinPer | 0:4ee8e6f5f993 | 179 | default: |
VinPer | 0:4ee8e6f5f993 | 180 | break; |
VinPer | 0:4ee8e6f5f993 | 181 | } |
VinPer | 0:4ee8e6f5f993 | 182 | } |
VinPer | 0:4ee8e6f5f993 | 183 | |
VinPer | 0:4ee8e6f5f993 | 184 | void writeStringToOLED(string str, int x, int y) { |
VinPer | 0:4ee8e6f5f993 | 185 | spiOLED.setTextCursor(x, y); |
VinPer | 0:4ee8e6f5f993 | 186 | spiOLED.fillRect(x, y, 128, 8, 0); |
VinPer | 0:4ee8e6f5f993 | 187 | for(int i = 0; i < str.length(); i++) { |
VinPer | 0:4ee8e6f5f993 | 188 | spiOLED.writeChar(str[i]); |
VinPer | 0:4ee8e6f5f993 | 189 | } |
VinPer | 0:4ee8e6f5f993 | 190 | spiOLED.display(); |
VinPer | 0:4ee8e6f5f993 | 191 | } |
VinPer | 0:4ee8e6f5f993 | 192 | |
VinPer | 0:4ee8e6f5f993 | 193 | // Mostra todas as leituras atuais |
VinPer | 0:4ee8e6f5f993 | 194 | void showStatus() { |
VinPer | 0:4ee8e6f5f993 | 195 | hc.printf("Presença: %d\nLDR: %.5f\nHigrometro Terra: %.5f\nHigrometro Agua: %.5f", |
VinPer | 0:4ee8e6f5f993 | 196 | pres.read(), |
VinPer | 0:4ee8e6f5f993 | 197 | ldr.read(), |
VinPer | 0:4ee8e6f5f993 | 198 | hygroEarth.read(), |
VinPer | 0:4ee8e6f5f993 | 199 | hygroWater.read()); |
VinPer | 0:4ee8e6f5f993 | 200 | } |
VinPer | 0:4ee8e6f5f993 | 201 | |
VinPer | 0:4ee8e6f5f993 | 202 | // Rega a planta a força, desde que tenha água no reservatório |
VinPer | 0:4ee8e6f5f993 | 203 | void waterPlant() { |
VinPer | 0:4ee8e6f5f993 | 204 | if(hygroWater.read() > waterLimit) waterCritical(); |
VinPer | 0:4ee8e6f5f993 | 205 | // ... |
VinPer | 0:4ee8e6f5f993 | 206 | } |
VinPer | 0:4ee8e6f5f993 | 207 | |
VinPer | 0:4ee8e6f5f993 | 208 | // Interrompe o funcionamento do vaso até que seja alimentado com água |
VinPer | 0:4ee8e6f5f993 | 209 | void waterCritical() { |
VinPer | 0:4ee8e6f5f993 | 210 | drawDead(); |
VinPer | 0:4ee8e6f5f993 | 211 | |
VinPer | 0:4ee8e6f5f993 | 212 | while(hygroWater.read() > waterLimit) { |
VinPer | 0:4ee8e6f5f993 | 213 | // whatever?! |
VinPer | 0:4ee8e6f5f993 | 214 | |
VinPer | 0:4ee8e6f5f993 | 215 | wait(1); |
VinPer | 0:4ee8e6f5f993 | 216 | } |
VinPer | 0:4ee8e6f5f993 | 217 | |
VinPer | 0:4ee8e6f5f993 | 218 | drawIdle(); |
VinPer | 0:4ee8e6f5f993 | 219 | } |
VinPer | 0:4ee8e6f5f993 | 220 | |
VinPer | 0:4ee8e6f5f993 | 221 | // Liga/desliga os LEDs |
VinPer | 0:4ee8e6f5f993 | 222 | void toggleLED() { |
VinPer | 0:4ee8e6f5f993 | 223 | ledStatus = !ledStatus; |
VinPer | 0:4ee8e6f5f993 | 224 | // ... |
VinPer | 0:4ee8e6f5f993 | 225 | } |
VinPer | 0:4ee8e6f5f993 | 226 | |
VinPer | 0:4ee8e6f5f993 | 227 | // Desenha uma carinha feliz ^u^ |
VinPer | 0:4ee8e6f5f993 | 228 | void drawSmile() { |
VinPer | 0:4ee8e6f5f993 | 229 | spiOLED.drawCircle(12, 20, 9, 1); |
VinPer | 0:4ee8e6f5f993 | 230 | spiOLED.fillRect(0, 5, 22, 15, 0); |
VinPer | 0:4ee8e6f5f993 | 231 | spiOLED.fillTriangle(2, 15, 10, 15, 6, 7, 1); |
VinPer | 0:4ee8e6f5f993 | 232 | spiOLED.fillTriangle(3, 15, 9, 15, 6, 8, 0); |
VinPer | 0:4ee8e6f5f993 | 233 | spiOLED.fillTriangle(14, 15, 22, 15, 18, 7, 1); |
VinPer | 0:4ee8e6f5f993 | 234 | spiOLED.fillTriangle(15, 15, 21, 15, 18, 8, 0); |
VinPer | 0:4ee8e6f5f993 | 235 | spiOLED.setTextSize(2); |
VinPer | 0:4ee8e6f5f993 | 236 | writeStringToOLED("Hello!", 30, 10); |
VinPer | 0:4ee8e6f5f993 | 237 | } |
VinPer | 0:4ee8e6f5f993 | 238 | |
VinPer | 0:4ee8e6f5f993 | 239 | void drawIdle() { |
VinPer | 0:4ee8e6f5f993 | 240 | spiOLED.drawCircle(12, 20, 9, 1); |
VinPer | 0:4ee8e6f5f993 | 241 | spiOLED.fillRect(0, 5, 22, 15, 0); |
VinPer | 0:4ee8e6f5f993 | 242 | spiOLED.fillRect(7, 6, 2, 10, 1); |
VinPer | 0:4ee8e6f5f993 | 243 | spiOLED.fillRect(16, 6, 2, 10, 1); |
VinPer | 0:4ee8e6f5f993 | 244 | spiOLED.setTextSize(2); |
VinPer | 0:4ee8e6f5f993 | 245 | writeStringToOLED("All ok!", 40, 10); |
VinPer | 0:4ee8e6f5f993 | 246 | } |
VinPer | 0:4ee8e6f5f993 | 247 | |
VinPer | 0:4ee8e6f5f993 | 248 | void drawSleep() { |
VinPer | 0:4ee8e6f5f993 | 249 | int y = 1; |
VinPer | 0:4ee8e6f5f993 | 250 | while(sleepCycle) { |
VinPer | 0:4ee8e6f5f993 | 251 | spiOLED.clearDisplay(); |
VinPer | 0:4ee8e6f5f993 | 252 | spiOLED.drawCircle(10, 23, 3, 1); |
VinPer | 0:4ee8e6f5f993 | 253 | spiOLED.fillRect(2, 12, 8, 2, 1); |
VinPer | 0:4ee8e6f5f993 | 254 | spiOLED.fillRect(15, 12, 8, 2, 1); |
VinPer | 0:4ee8e6f5f993 | 255 | spiOLED.setTextSize(1); |
VinPer | 0:4ee8e6f5f993 | 256 | writeStringToOLED("z", 35, 16 + y * 3); |
VinPer | 0:4ee8e6f5f993 | 257 | spiOLED.setTextSize(2); |
VinPer | 0:4ee8e6f5f993 | 258 | writeStringToOLED("z", 45, 11 - y * 3); |
VinPer | 0:4ee8e6f5f993 | 259 | spiOLED.setTextSize(3); |
VinPer | 0:4ee8e6f5f993 | 260 | writeStringToOLED("z", 65, 6 + y * 3); |
VinPer | 0:4ee8e6f5f993 | 261 | spiOLED.setTextSize(4); |
VinPer | 0:4ee8e6f5f993 | 262 | writeStringToOLED("z", 90, 1 - y * 3); |
VinPer | 0:4ee8e6f5f993 | 263 | wait(1); |
VinPer | 0:4ee8e6f5f993 | 264 | y = y * -1; |
VinPer | 0:4ee8e6f5f993 | 265 | |
VinPer | 0:4ee8e6f5f993 | 266 | // ... |
VinPer | 0:4ee8e6f5f993 | 267 | if (seconds > 86400) sleepCycle = false; |
VinPer | 0:4ee8e6f5f993 | 268 | } |
VinPer | 0:4ee8e6f5f993 | 269 | } |
VinPer | 0:4ee8e6f5f993 | 270 | |
VinPer | 0:4ee8e6f5f993 | 271 | void drawDead() { |
VinPer | 0:4ee8e6f5f993 | 272 | spiOLED.drawCircle(13, 27, 7, 1); |
VinPer | 0:4ee8e6f5f993 | 273 | spiOLED.fillRect(0, 28, 22, 15, 0); |
VinPer | 0:4ee8e6f5f993 | 274 | spiOLED.drawLine(2, 15, 10, 7, 1); |
VinPer | 0:4ee8e6f5f993 | 275 | spiOLED.drawLine(2, 7, 10, 15, 1); |
VinPer | 0:4ee8e6f5f993 | 276 | spiOLED.drawLine(16, 15, 24, 7, 1); |
VinPer | 0:4ee8e6f5f993 | 277 | spiOLED.drawLine(16, 7, 24, 15, 1); |
VinPer | 0:4ee8e6f5f993 | 278 | spiOLED.setTextSize(2); |
VinPer | 0:4ee8e6f5f993 | 279 | writeStringToOLED("Help!", 50, 6); |
VinPer | 0:4ee8e6f5f993 | 280 | spiOLED.setTextSize(1); |
VinPer | 0:4ee8e6f5f993 | 281 | writeStringToOLED("Need water!!", 50, 22); |
VinPer | 0:4ee8e6f5f993 | 282 | } |