-
-
Save delhoume/2688aa50d798dbb94c9adf8e77f0454b to your computer and use it in GitHub Desktop.
| /* | |
| TPM2.NET protocol handler | |
| Works with Jinx LED software | |
| */ | |
| #include <ESP8266WiFi.h> | |
| #include <WiFiUdp.h> | |
| #include <FastLED.h> | |
| #include <WiFiManager.h> | |
| #include <Ticker.h> | |
| #define TMP2NET_IN_PORT 65506 | |
| #define TMP2NET_OUT_PORT 65442 | |
| WiFiUDP udp; | |
| const uint16_t width = 8; | |
| const uint16_t height = 8; | |
| const uint16_t numleds = width * height; | |
| const uint16_t payload = numleds * 3; | |
| const uint8_t packet_start_byte = 0x9c; | |
| const uint8_t packet_type_data = 0xda; | |
| const uint8_t packet_type_cmd = 0xc0; | |
| const uint8_t packet_type_response = 0xaa; | |
| const uint8_t packet_end_byte = 0x36; | |
| const uint8_t packet_response_ack = 0xac; | |
| // maximum udp esp8266 payload = 1460 -> 484 rgb leds per frame (22x22 matrix) | |
| // then you have to use packet numbers and split the payload | |
| const uint16_t expected_packet_size = payload + 7; | |
| uint8_t data[payload]; | |
| #if defined(NO_WIFI_MANAGER) | |
| const char *ssid = ""; | |
| const char *password = ""; | |
| IPAddress local_ip(192, 168, 1, 200); | |
| IPAddress gateway_ip(192, 168, 1, 1); | |
| IPAddress subnet_ip(255, 255, 255, 0); | |
| #endif | |
| // Param for different pixel layouts | |
| // TODO: verify vertical order (if starting from top or bottom) | |
| const bool kMatrixSerpentineLayout = true; | |
| uint16_t XY(uint8_t x, uint8_t y) { | |
| uint16_t i; | |
| if (kMatrixSerpentineLayout == false) { | |
| i = (y * width) + x; | |
| } else { | |
| if (y & 0x01) { | |
| // Odd rows run backwards | |
| uint8_t reverseX = (width - 1) - x; | |
| i = (y * width) + reverseX; | |
| } else { | |
| // Even rows run forwards | |
| i = (y * width) + x; | |
| } | |
| } | |
| return i; | |
| } | |
| #define LED_PIN 3 | |
| CRGB leds[numleds]; | |
| Ticker ticker; | |
| void tick() { | |
| int state = digitalRead(BUILTIN_LED); | |
| digitalWrite(BUILTIN_LED, !state); | |
| } | |
| void configModeCallback (WiFiManager *myWiFiManager) { | |
| Serial.println("Entered config mode"); | |
| Serial.println(WiFi.softAPIP()); | |
| //entered config mode, make led toggle faster | |
| ticker.detach(); | |
| ticker.attach(0.2, tick); | |
| } | |
| const CRGB ipalette[3] = { | |
| { 0, 0, 0}, // black | |
| { 255, 255, 255}, // white | |
| { 255, 0, 200 } // pink | |
| }; | |
| const uint8_t invader[8][8] PROGMEM = { | |
| {0, 1, 0, 1, 1, 0, 1, 0}, | |
| {0, 0, 1, 1, 1, 1, 0, 0}, | |
| {0, 1, 2, 1, 1, 2, 1, 0}, | |
| {1, 1, 1, 1, 1, 1, 1, 1}, | |
| {1, 0, 1, 1, 1, 1, 0, 1}, | |
| {1, 0, 1, 0, 0, 1, 0, 1}, | |
| {0, 0, 1, 0, 0, 1, 0, 0}, | |
| {0, 1, 1, 0, 0, 1, 1, 0} | |
| }; | |
| void displayInvader() { | |
| for (uint8_t y = 0; y < height; ++y) { | |
| for (uint8_t x = 0; x < width; ++x) { | |
| uint8_t idx = pgm_read_byte(&invader[y][x]); | |
| leds[XY(x, y)] = ipalette[idx]; | |
| } | |
| } | |
| FastLED.show(); | |
| // TODO: display fps on OLED | |
| FastLED.getFPS(); | |
| } | |
| void setup() { | |
| Serial.begin(115200); | |
| delay(10); | |
| pinMode(BUILTIN_LED, OUTPUT); | |
| ticker.attach(0.6, tick); | |
| FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, numleds); | |
| FastLED.countFPS(); | |
| FastLED.setBrightness(128); // limit power usage for testing | |
| // make the display show something | |
| displayInvader(); | |
| #if defined(NO_WIFI_MANAGER) | |
| Serial.print("Connecting to "); | |
| Serial.println(ssid); | |
| WiFi.begin(ssid, password); | |
| // is is necessary ? | |
| WiFi.config(local_ip, gateway_ip, subnet_ip); | |
| while (WiFi.status() != WL_CONNECTED) { | |
| delay(1000); | |
| Serial.print("."); | |
| } | |
| #else | |
| WiFiManager wifiManager; | |
| // wifiManager.resetSettings(); | |
| // wifiManager.setDebugOutput(false); | |
| wifiManager.setAPCallback(configModeCallback); | |
| wifiManager.autoConnect("ledmatrix", "ledmatrix"); | |
| #endif | |
| ticker.detach(); | |
| digitalWrite(BUILTIN_LED, HIGH); | |
| Serial.println(""); | |
| Serial.println("WiFi connected"); | |
| Serial.println("IP address: "); | |
| Serial.println(WiFi.localIP()); | |
| long rssi = WiFi.RSSI(); | |
| // -120 to 0 DBm | |
| // int quality; | |
| // if(rssi <= -100) | |
| // quality = 0; | |
| // else if(rssi >= -50) | |
| // quality = 100; | |
| // else | |
| // quality = 2 * (rssi + 100); | |
| // Serial.print("signal quality:"); | |
| // Serial.println(quality); | |
| /* | |
| Android code | |
| private static final int MIN_RSSI = -100; | |
| private static final int MAX_RSSI = -55; | |
| public static final int RSSI_LEVELS = 5; | |
| public static int calculateSignalLevel(int rssi, int numLevels) { | |
| if (rssi <= MIN_RSSI) { | |
| return 0; | |
| } else if (rssi >= MAX_RSSI) { | |
| return numLevels - 1; | |
| } else { | |
| float inputRange = (MAX_RSSI - MIN_RSSI); | |
| float outputRange = (numLevels - 1); | |
| return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange); | |
| } | |
| } | |
| */ | |
| Serial.print("signal strength: "); | |
| Serial.print(rssi); | |
| Serial.println(" dBm"); | |
| udp.begin(TMP2NET_IN_PORT); | |
| } | |
| void sendAck() { | |
| udp.beginPacket(udp.remoteIP(), TMP2NET_OUT_PORT); | |
| udp.write(&packet_response_ack, 1); | |
| udp.endPacket(); | |
| } | |
| void fillMatrix() { | |
| for (uint8_t y = 0; y < height; ++y) { | |
| uint8_t *ptr = data + y * 3 * width; | |
| for (uint8_t x = 0; x < width; ++x, ptr += 3) { | |
| leds[XY(x, y)].setRGB(ptr[0], ptr[1], ptr[2]); | |
| } | |
| } | |
| FastLED.show(); | |
| } | |
| void fillMatrix(CRGB color) { | |
| // do not care about XY order | |
| for (uint16_t l = 0; l < numleds; ++l) { | |
| leds[l].setRGB(color.r, color.g, color.b); | |
| } | |
| // fill_solid(leds, numleds, color); | |
| FastLED.show(); | |
| } | |
| uint32_t frameCounter = 0; | |
| void loop() { | |
| uint16_t packet_size = udp.parsePacket(); | |
| // then parse to check | |
| if (udp.read() != packet_start_byte) | |
| return; | |
| // packet type | |
| uint8_t ptype = udp.read(); | |
| uint16_t frame_size = (udp.read() << 8) | udp.read(); | |
| // skip packet number and number of packets | |
| udp.read(); | |
| udp.read(); | |
| switch (ptype) { | |
| case packet_type_response: | |
| sendAck(); | |
| break; | |
| case packet_type_data: { | |
| if (frame_size != payload) | |
| return; | |
| // TODO: check if Jinx! sends data in snake order | |
| // then code will be much simpler and faster | |
| // TODO: fill the matrix directly, in the (char*)leds array | |
| // udp.read((char*)leds, payload); | |
| // FastLed.show(); | |
| udp.read(data, payload); | |
| // now process the data (fill the matrix) | |
| fillMatrix(); | |
| ++frameCounter; | |
| break; | |
| } | |
| case packet_type_cmd: { | |
| // read the command | |
| uint8_t command; | |
| uint8_t rgb[3]; | |
| udp.read(&command, 1); // not used yet | |
| udp.read(rgb, 3); | |
| fillMatrix(CRGB(rgb[0], rgb[1], rgb[2])); | |
| break; | |
| } | |
| } | |
| // skip end byte, maybe not neccessary | |
| udp.read(); | |
| } |
It should work with any FastLED supported chipset
hello how are you? could you help me configure it.
Hola no me funciona con el ESP01. Intenté de mil maneras, se sube, lo configuro y no me anda.
El tamaño de la matrix es de 30 de ancho por 15 de alto. No me prende no siquera un led solo
What might happen is that 30x15x3 is too large for a single UDP packet on esp8266, you have to split the load in rows, I have some sample code on my https://github.com/delhoume/wemos32x32/blob/master/wemos32x32.ino, see loopUDP(), where frames are 32x8x3 (width 32 height 8 and RGB).
The matrix should already work with some fastled sample code. Is the matrix working ?
please give more info on WiFiManager.h which library is this github link? also how does this connect to jinx. does the esp and jinx need to connect to same wifi?
it is well known esp8266 https://github.com/tzapu/WiFiManager available in library manager in Arduino IDE
Of course Jinx! and esp8266 must be on the same wifi network, you just have to know the esp8266 IP address and use it in Jinx!
thank you for your speedy reply. you are a savior
hola , funciona en ws2811 ?