diff --git a/ESP/mqtt_test/mqtt_test.ino b/ESP/mqtt_test/mqtt_test.ino new file mode 100644 index 0000000..81157d1 --- /dev/null +++ b/ESP/mqtt_test/mqtt_test.ino @@ -0,0 +1,101 @@ +#include +#include +#include + +const char* ssid = "Verbruggen"; +const char* password = "D93579084A"; +const char* mqttServer = "10.1.13.173"; +const int mqttPort = 1883; +const char* mqttTopic = "test"; + +const int gpioPin = 25; // GPIO pin to check for shorting +const unsigned long debounceDelay = 50; // Debounce delay in milliseconds + +WiFiClient wifiClient; +PubSubClient mqttClient(wifiClient); + +TaskHandle_t mqttTaskHandle = NULL; + +Bounce debouncer = Bounce(); + +volatile int pressCounter = 0; + +void setupWiFi() { + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(1000); + Serial.println("Connecting to WiFi..."); + } + Serial.println("Connected to WiFi"); +} + +void callback(char* topic, byte* payload, unsigned int length) { + // This function is called when a message is received from the MQTT server + // Add your desired code here to handle the received message +} + +void reconnectMQTT() { + while (!mqttClient.connected()) { + Serial.println("Connecting to MQTT server..."); + if (mqttClient.connect("ESP32Client")) { + Serial.println("Connected to MQTT server"); + mqttClient.subscribe(mqttTopic); + } else { + Serial.print("MQTT connection failed, rc="); + Serial.print(mqttClient.state()); + Serial.println(" Retrying in 5 seconds..."); + delay(5000); + } + } +} + +void mqttTask(void* parameter) { + for (;;) { + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); // Wait for notification + + if (mqttClient.connected()) { + String message = "GPIO pin shorted! Count: " + String(pressCounter); + mqttClient.publish(mqttTopic, message.c_str()); + Serial.println("Message sent to MQTT server"); + pressCounter++; + } + } +} + +void setup() { + Serial.begin(115200); + pinMode(gpioPin, INPUT_PULLUP); + + debouncer.attach(gpioPin); + debouncer.interval(debounceDelay); + + setupWiFi(); + mqttClient.setServer(mqttServer, mqttPort); + mqttClient.setCallback(callback); + + xTaskCreatePinnedToCore( + mqttTask, // Task function + "mqttTask", // Task name + 4096, // Stack size (bytes) + NULL, // Task parameter + 1, // Task priority + &mqttTaskHandle, // Task handle + 1 // Task core (0 or 1) + ); +} + +void loop() { + if (!mqttClient.connected()) { + reconnectMQTT(); + } + mqttClient.loop(); + + debouncer.update(); + if (debouncer.fell()) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(mqttTaskHandle, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } +} \ No newline at end of file diff --git a/faceTest.py b/faceTest.py new file mode 100644 index 0000000..d156f8e --- /dev/null +++ b/faceTest.py @@ -0,0 +1,47 @@ +matrix = [[" " for _ in range(64)] for _ in range(32)] + +# LED positions +led_positions = [ + # Ears + (10, 4), (10, 5), (10, 6), (10, 7), + (30, 4), (30, 5), (30, 6), (30, 7), + + # Face outline + (9, 10), (10, 9), (10, 10), (10, 11), (10, 12), (10, 13), (10, 14), (10, 15), (10, 16), (10, 17), (10, 18), + (10, 19), (10, 20), (10, 21), (10, 22), (10, 23), (10, 24), (10, 25), (10, 26), (10, 27), (10, 28), (10, 29), + (10, 30), (10, 31), (11, 8), (11, 18), (11, 19), (11, 20), (11, 21), (11, 22), (11, 23), (11, 24), (11, 25), + (11, 26), (11, 27), (11, 28), (11, 29), (11, 30), (11, 31), (12, 7), (12, 8), (12, 18), (12, 19), (12, 20), + (12, 21), (12, 22), (12, 23), (12, 24), (12, 25), (12, 26), (12, 27), (12, 28), (12, 29), (12, 30), (12, 31), + (13, 6), (13, 7), (13, 8), (13, 18), (13, 19), (13, 20), (13, 21), (13, 22), (13, 23), (13, 24), (13, 25), + (13, 26), (13, 27), (13, 28), (13, 29), (13, 30), (13, 31), (14, 5), (14, 6), (14, 7), (14, 18), (14, 19), + (14, 20), (14, 21), (14, 22), (14, 23), (14, 24), (14, 25), (14, 26), (14, 27), (14, 28), (14, 29), (14, 30), + (14, 31), (15, 4), (15, 5), (15, 6), (15, 18), (15, 19), (15, 20), (15, 21), (15, 22), (15, 23), (15, 24), + (15, 25), (15, 26), (15, 27), (15, 28), (15, 29), (15, 30), (15, 31), (16, 3), (16, 4), (16, 5), (16, 18), + (16, 19), (16, 20), (16, 21), (16, 22), (16, 23), (16, 24), (16, 25), (16, 26), (16, 27), (16, 28), (16, 29), + (16, 30), (16, 31), (17, 3), (17, 4), (17, 5), (17, 18), (17, 19), (17, 20), (17, 21), (17, 22), (17, 23), + (17, 24), (17, 25), (17, 26), (17, 27), (17, 28), (17, 29), (17, 30), (17, 31), (18, 3), (18, 4), (18, 5), + (18, 18), (18, 19), (18, 20), (18, 21), (18, 22), (18, 23), (18, 24), (18, 25), (18, 26), (18, 27), (18, 28), + (18, 29), (18, 30), (18, 31), (19, 4), (19, 5), (19, 18), (19, 19), (19, 20), (19, 21), (19, 22), (19, 23), + (19, 24), (19, 25), (19, 26), (19, 27), (19, 28), (19, 29), (19, 30), (19, 31), + + # Eyes + (22, 17), (22, 18), (22, 19), + (42, 17), (42, 18), (42, 19), + + # Nose + (32, 12), (32, 13), (32, 14), (32, 15), + + # Mouth + (26, 20), (26, 21), (26, 22), (26, 23), (26, 24), (26, 25), (26, 26), (26, 27), (26, 28), (26, 29), (26, 30), + (27, 20), (27, 21), (27, 22), (27, 23), (27, 24), (27, 25), (27, 26), (27, 27), (27, 28), (27, 29), (27, 30), + (28, 20), (28, 21), (28, 22), (28, 23), (28, 24), (28, 25), (28, 26), (28, 27), (28, 28), (28, 29), (28, 30), + (29, 20), (29, 21), (29, 22), (29, 23), (29, 24), (29, 25), (29, 26), (29, 27), (29, 28), (29, 29), (29, 30), +] + +# Set LED values +for x, y in led_positions: + matrix[y][x] = "1" + +# Print the matrix +for row in matrix: + print("".join(row)) \ No newline at end of file diff --git a/rpi/roy-test.py b/rpi/roy-test.py new file mode 100644 index 0000000..613d61c --- /dev/null +++ b/rpi/roy-test.py @@ -0,0 +1,52 @@ +from samplebase import SampleBase +from rgbmatrix import RGBMatrix, RGBMatrixOptions +import paho.mqtt.client as mqtt + +class PulsingColors(SampleBase): + color = 0 + def __init__(self, *args, **kwargs): + super(PulsingColors, self).__init__(*args, **kwargs) + + def run(self): + self.offscreen_canvas = self.matrix.CreateFrameCanvas() + continuum = 0 + + while True: + self.usleep(5 * 1000) + + if(self.color == 1): + self.offscreen_canvas.Fill(255,255,255) + else: + self.offscreen_canvas_Fill(255,0,0) + self.offscreen_canvas.brightness = 100 + self.offscreen_canvas = self.matrix.SwapOnVSync(self.offscreen_canvas) + + def toggleColor(self): + if(self.color == 1): + self.color = 0 + else: + self.color = 1 + +def on_connect(client, userdata, flags, rc): + print("Connected to MQTT broker with result code " + str(rc)) + client.subscribe("test") + +def on_message(client, userdata, msg): + print("Received message: " + str(msg.payload.decode("utf-8"))) + pulsing_colors.toggleColor() + pulsing_colors.run() + +pulsing_colors = PulsingColors() + +client = mqtt.Client() +client.on_connect = on_connect +client.on_message = on_message + +client.connect("10.1.13.173", 1883, 60) # Replace with your MQTT broker's address + +client.loop_forever() + +# Main function +if __name__ == "__main__": + if (not pulsing_colors.process()): + pulsing_colors.print_help() diff --git a/visual.py b/visual.py new file mode 100644 index 0000000..a774ac1 --- /dev/null +++ b/visual.py @@ -0,0 +1,266 @@ +import math +import os +import time + +class Point2D: + x = 0 + y = 0 + + def __init__(self, x, y, value = 0): + self.x = x + self.y = y + + def round(self): + self.x = round(self.x) + self.y = round(self.y) + return self + + def __eq__(self, other): + return (self.x, self.y) == (other.x, other.y) + +def print_grid_tight(grid): + width, height = len(grid), len(grid[0]) + for y in range(height): + for x in range(width): + if(grid[x][y] == 1): + blockchar = u"\u2588" + print((f"\033[38;5;{250}m{blockchar*2}"), end = "") + else: + print((" "), end = "") + print() + + +#def print_grid(grid): +# width, height = len(grid[0]), len(grid) +# for x in range(height): +# print(("+" + "----") * width + "+") +# print("|", end = "") +# for y in range(width): +# if(grid[x][y] == 1): +# print((" " + u"\u2588" + u"\u2588" + " ")+ "|", end = "") +# else: +# print((" ") + "|", end = "") +# if(y == width-1): +# print() +# print(("+" + "----") * width + "+") + + +grid = [[0 for y in range(32)] for x in range(64)] + + + +def shift_right(grid): + width, height = len(grid[0]), len(grid) + for x in range(height): + for y in range(width-1, 0, -1): + grid[x][y] = grid[x][y-1] + + +def shift_left(grid): + width, height = len(grid[0]), len(grid) + for x in range(height): + for y in range(1, width): + grid[x][y-1] = grid[x][y] + + +def shift_down(grid): + width, height = len(grid[0]), len(grid) + for x in range(height-1, 0, -1): + for y in range(width): + grid[x][y] = grid[x-1][y] + +def shift_up(grid): + width, height = len(grid[0]), len(grid) + for x in range(1, height): + for y in range(width): + grid[x-1][y] = grid[x][y] + + +# line drawing funtion +def draw_line(grid, start: Point2D, end: Point2D, color): + dx = abs(end.x - start.x) + dy = abs(end.y - start.y) + length = dx if dx > dy else dy # diagonal_distance + if length > 0: + for i in range(length+1): + t = i / length + x = start.x + int(t * (end.x - start.x)) # linear interpolation + y = start.y + int(t * (end.y - start.y)) # linear interpolation + grid[x][y] = color + else: + grid[start.x][start.y] = color + + + +# triangle drawing helper functions +def fillBottomFlatTriangle(grid, point1, point2, point3, color): + invslope1 = (point2.x - point1.x) / (point2.y - point1.y) + invslope2 = (point3.x - point1.x) / (point3.y - point1.y) + + curx1 = point1.x + curx2 = point1.x + + for scanlineY in range(point1.y, point2.y+1): + draw_line(grid, Point2D(int(curx1), scanlineY), Point2D(int(curx2), scanlineY), color) + curx1 += invslope1 + curx2 += invslope2 + +def fillTopFlatTriangle(grid, point1, point2, point3, color): + invslope1 = (point3.x - point1.x) / (point3.y - point1.y) + invslope2 = (point3.x - point2.x) / (point3.y - point2.y) + + curx1 = point3.x + curx2 = point3.x + + for scanlineY in range(point3.y, point1.y-1, -1): + draw_line(grid, Point2D(int(curx1), scanlineY), Point2D(int(curx2), scanlineY), color) + curx1 -= invslope1 + curx2 -= invslope2 + +def sortPoints2DAscendingByY(points: tuple[Point2D]) -> tuple[Point2D]: + return tuple(sorted(points, key=lambda point: point.y)) + + +# triangle drawing function +def draw_triangle(grid, point1: Point2D, point2: Point2D, point3: Point2D, color): + # at first sort the three vertices by y-coordinate ascending so point1 is the topmost vertex + (point1, point2, point3) = sortPoints2DAscendingByY((point1, point2, point3)) + + # here we know that point1.y <= point2.y <= point3.y + # check for trivial case of bottom-flat triangle + if point2.y == point3.y: + fillBottomFlatTriangle(grid, point1, point2, point3, color) + # check for trivial case of top-flat triangle + elif point1.y == point2.y: + fillTopFlatTriangle(grid, point1, point2, point3, color) + else: + # general case - split the triangle in a topflat and bottom-flat one + point4 = Point2D( + int(point1.x + ((float)(point2.y - point1.y) / (float)(point3.y - point1.y)) * (point3.x - point1.x)), point2.y) + fillBottomFlatTriangle(grid, point1, point2, point4, color) + fillTopFlatTriangle(grid, point2, point4, point3, color) + + + +def pos_on_circle(center: Point2D, radius: float, angle: float) -> Point2D: + angle = angle * 3.14159 / 180 + x = center.x + radius * math.cos(angle) + y = center.y + radius * math.sin(angle) + return Point2D(x, y) + + +# function for getting all the points on a circle +def get_circle_points(grid, center: Point2D, radius) -> list[Point2D]: + points = list() + for r in range(360): + newPoint = pos_on_circle(center, radius, r).round() + if not newPoint in points: + points.append(newPoint) + + return points + +points: list[Point2D] = get_circle_points(grid, Point2D(16,16), 6) + + +#flag is next step will be shift left +direction = 0 +hand = Point2D +t = 0 + +# top left corner +grid[0][0] = 1 +grid[0][1] = 1 +grid[1][0] = 1 + +# top right corner +grid[62][0] = 1 +grid[63][0] = 1 +grid[63][1] = 1 + +# lower right corner +grid[62][31] = 1 +grid[63][31] = 1 +grid[63][30] = 1 + +# lower left corner +grid[1][31] = 1 +grid[0][31] = 1 +grid[0][30] = 1 + + +draw_triangle(grid, Point2D(5,5), Point2D(5,10), Point2D(10,10), 1) +#draw_triangle(grid, Point2D(13,4), Point2D(18,12), Point2D(20,4), 1) +#draw_triangle(grid, Point2D(20,18), Point2D(29,14), Point2D(25,25), 1) + +print_grid_tight(grid) + +def next_tick_circle(): + # clear screen + os.system('cls||clear') + + #update state in a square movement + #global direction + #match direction: + # case 3: + # shift_up(grid) + # direction = 0 + # case 2: + # shift_left(grid) + # direction += 1 + # case 1: + # shift_down(grid) + # direction += 1 + # case 0: + # shift_right(grid) + # direction += 1 + global hand + global t + global points + + hand = points[t] + color = 0 + + if grid[hand.x][hand.y] is 0: + color = 1 + + draw_line(grid, Point2D(16,16), hand, color) + + t = t+1 + if t is len(points): + t = 0 + + + # print current state + print_grid_tight(grid) + + + + + +while True: + time.sleep(0.1) + next_tick_circle() + + + +#grayscale from 232(black) to 255(white) +print(f"\033[38;5;{250}m {num2} \033[0;0m\n") + +# printing colors +# colorspep8.py +def colors_16(color_): + return("\033[2;{num}m {num} \033[0;0m".format(num=str(color_))) + + +def colors_256(color_): + num1 = str(color_) + num2 = str(color_).ljust(3, ' ') + if color_ % 16 == 0: + return(f"\033[38;5;{num1}m {num2} \033[0;0m\n") + else: + return(f"\033[38;5;{num1}m {num2} \033[0;0m") + +print("The 16 colors scheme is:") +print(' '.join([colors_16(x) for x in range(30, 38)])) +print("\nThe 256 colors scheme is:") +print(' '.join([colors_256(x) for x in range(256)])) \ No newline at end of file