In our house old rotary phones are used as a remote for Sonos, Philips Hue and to ring the door bell. Turning the dial on one of the phones starts playing an MP3 on the phone. Turning the dial of the phone in another room dims the light, or turns it on or off.
We use an old Ericofoon, a red and green Dutch T65:
I connected the 2 pins of the phones to an ESP8226 (nodemcu). You can buy them for cheap on Chinese webshops.
The C code below is counting pulses. I used platformio to compile the ESP8226 code and upload it. The ESP8226 requests a Raspberry Pi to evaluate an URL. The Python code for the Raspberry Pi will be subject of another post.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
/* DHT */ # define DHTTYPE DHT11 # define DHTPIN D2 DHT dht(DHTPIN, DHTTYPE); const char* ssid = "mywifi"; const char* password = "blackmirr0r"; /* LED */ Chrono chrono_led; int pin_led = D4; // LED_BUILTIN int state_led = LOW; /* Rotary All */ enum enum_state {DOWN_FIRST, UP, DOWN}; /* server */ ESP8266WebServer server(80); void log(int dial, int elapsed, int state) { if (state == 0) { Serial.printf("dial=%5d, elapsed=%5d, state=DOWN_FIRST\n", dial, elapsed); } else if (state == 1) { Serial.printf("dial=%5d, elapsed=%5d, state=UP\n", dial, elapsed); } else { Serial.printf("dial=%5d, elapsed=%5d, state=DOWN\n", dial, elapsed); } } void call_server(int device, int dial) { HTTPClient http; int httpCode; char url[128]; sprintf(url, "http://192.168.1.11:8002/casa/index.php?action=dial&dial=%d&device=%d", dial, device); Serial.println(url); http.begin(url); httpCode = http.GET(); // httpCode will be negative on error if (httpCode > 0) { if (httpCode == HTTP_CODE_OK) { String payload = http.getString(); Serial.println(payload); } } else { Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); } http.end(); } void loop_blink_led() { if (state_led == LOW) { if (chrono_led.elapsed() > 1000) { state_led = HIGH; digitalWrite(pin_led, state_led); chrono_led.restart(); } } else { if (chrono_led.elapsed() > 10000) { state_led = LOW; digitalWrite(pin_led, state_led); chrono_led.restart(); } } } class Rotary { public: Rotary(int, int, double, double); void setup(); void loop(); void print(); private: Chrono chrono_rotary; int pin_in = D6; int device; int previous_value; double period_min = 25; // in ms; minimum duration of a high double period_max = 80; // in ms; maximum duration of a full period (1 high + 1 low) int dial = 0; enum_state state = DOWN_FIRST; }; Rotary::Rotary(int d, int pin, double pmin, double pmax) { pin_in = pin; period_min = pmin; period_max = pmax; device = d; }; void Rotary::setup() { pinMode(pin_in, INPUT_PULLUP); chrono_rotary.restart(); }; void Rotary::loop() { int val; val = digitalRead(pin_in); switch(state) { case DOWN_FIRST: if (val == HIGH) { state = UP; log(dial,chrono_rotary.elapsed(),state); chrono_rotary.restart(); } break; case UP: if (val == LOW) { if (chrono_rotary.elapsed() > period_min) { state = DOWN; dial++; log(dial,chrono_rotary.elapsed(),state); chrono_rotary.restart(); } else { state = DOWN_FIRST; log(dial,chrono_rotary.elapsed(),state); } } break; case DOWN: if (chrono_rotary.elapsed() > period_max) { state = DOWN_FIRST; log(dial,chrono_rotary.elapsed(),state); call_server(device, dial); dial = 0; } else if ((val == HIGH) && (chrono_rotary.elapsed() > period_min)) { state = UP; log(dial,chrono_rotary.elapsed(),state); chrono_rotary.restart(); } break; } }; void Rotary::print() { int val; val = digitalRead(pin_in); if (previous_value != val) { Serial.printf("val=%5d, elapsed=%5d\n", val, chrono_rotary.elapsed()); chrono_rotary.restart(); previous_value = val; } } Rotary T65_red (11, D6, 25, 80); Rotary ericofoon(13, D7, 1, 130); void setup() { Serial.begin(9600); Serial.println("T65 Rotary"); T65_red.setup(); ericofoon.setup(); pinMode(pin_led, OUTPUT); chrono_led.restart(); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("Connection Failed! Rebooting..."); delay(5000); ESP.restart(); } Serial.println("Ready"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); dht.begin(); server.on("/", [](){ String buf = ""; float rh = dht.readHumidity(); float temp = dht.readTemperature(); // buf = "T=" + String(temp) + ",RH=" + String(rh); buf = String(temp) + "," + String(rh); Serial.println(buf); server.send(200, "text/plain", buf); state_led = LOW; digitalWrite(pin_led, state_led); delay(1000); state_led = HIGH; digitalWrite(pin_led, state_led); }); server.begin(); } void loop() { server.handleClient(); T65_red.loop(); delay(0.1); } |