This project was first published in our DF Chinese community. It aims to achieve a wireless handwritten dot matrix screen using UNIHIKER. It combines handwritten input on the UNIHIKER screen with Python OS library screenshotting. It then analyzes the handwritten traces on the image to extract coordinates. These coordinates are subsequently transmitted via TCP to Arduino for illuminating the dot matrix screen.
Here is all the hardware used in this project:
1. Dot Matrix Screen
Here I use 32x16 RGB LED Matrix Panel from DFRobot.
For more information about this panel can refer to the product wiki.
Connect the Arduino to the dot matrix screen according to the two diagrams above.
2. Arduino & WiFi Connection
Using the WiFiBee-MT7681, inserted into the Arduino expansion board. Here I've noticed that this WiFi module from the DFRobot official store is no longer available. So you can you search for alternative options.
3. Test Display
Connect UNIHIKER to the internet, load the socket library, press the A key sends "A", and press the B key sends "B".
s.connect(('192.168.31.38',1000))
"192.168.31.38" is the IP address for the WiFiBee-MT7681 connected to the network.
import socket
from unihiker import GUI
i=0
def on_buttonb_click_callback():
s.send(b'B')
def on_buttona_click_callback():
s.send(b'A')
u_gui=GUI()
u_gui.on_a_click(on_buttona_click_callback)
u_gui.on_b_click(on_buttonb_click_callback)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('192.168.31.38',1000))
while True:
pass
Arduino uses serial communication to receive information from WiFiBee-MT7681. When it receives "A", the dot matrix screen displays the letter "A", and when it receives "B", it clears the screen.
#include <Adafruit_GFX.h>
#include <RGBmatrixPanel.h>
#define CLK 8
#define LAT A3
#define OE 9
#define A A0
#define B A1
#define C A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);
void setup() {
Serial.begin(115200);
matrix.begin();
matrix.fillScreen(matrix.Color333(0, 0, 0));
matrix.setCursor(1, 0);
matrix.setTextSize(1);
matrix.setTextColor(matrix.Color333(7,0,0));
}
void loop() {
if ((Serial.available())) {
String mystr=Serial.readString();
if(mystr=="B"){
matrix.fillScreen(matrix.Color333(0, 0, 0));
}
else{
matrix.print(mystr);
}
}
4. Sending Coordinate Information
The UNIHIKER Python program captures handwritten traces and sends the coordinates of the traces.
import socket
from unihiker import GUI
import time
import os
import cv2
import numpy as np
pos_xy = []
def image_rotate(src, rotate=0):
h,w,c = src.shape
cos_val = np.cos(np.deg2rad(rotate))
sin_val = np.sin(np.deg2rad(rotate))
M = np.float32([[cos_val, -sin_val, 0], [sin_val, cos_val, 0]])
img = cv2.warpAffine(src, M, (w,h))
return img
def on_buttonb_click_callback():
u_gui.clear()
s.send(b'B')
def on_buttona_click_callback():
os.system("scrot -a 0,0,240,320 sc.png")
img = cv2.imread("sc.png")
img=cv2.resize(img,(16,32))
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
low = np.array([0, 0, 0])
high = np.array([180, 255, 46])
dst = cv2.inRange(src=hsv, lowerb=low, upperb=high)
xy = np.column_stack(np.where(dst==255))
mystr=b''
k=0
for c in xy:
for d in c:
mystr=mystr+b","+str(d).encode()
k+=1
if k==10:
mystr=str(k).encode()+mystr
print(mystr)
s.send(mystr)
k=0
mystr=b''
time.sleep(2)
if k>0:
mystr=str(k).encode()+mystr
print(mystr)
s.send(mystr)
u_gui=GUI()
u_gui.on_a_click(on_buttona_click_callback)
u_gui.on_b_click(on_buttonb_click_callback)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('192.168.31.38',1000))
def mouse_move(x, y):
global temp_time
temp_time = time.time()
pos_xy.append([x,y])
if len(pos_xy) > 1:
point_start = pos_xy[0]
for pos_tmp in pos_xy:
point_end = pos_tmp
line_text = u_gui.draw_line(x0=point_start[0],y0=point_start[1],x1=point_end[0],y1=point_end[1],width=20, color=(0,0,0))
point_start = point_end
def on_release(event):
pos_xy.clear()
u_gui.master.bind("<ButtonRelease>", on_release)
u_gui.on_mouse_move(mouse_move)
while True:
time.sleep(0.5)
5. Arduino Receive Display
Use custom function fenge, split the received string coordinates, use matrix.drawPixel to light the coordinates.
#include <Adafruit_GFX.h>
#include <RGBmatrixPanel.h>
#define CLK 8
#define LAT A3
#define OE 9
#define A A0
#define B A1
#define C A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);
void setup() {
Serial.begin(115200);
matrix.begin();
matrix.fillScreen(matrix.Color333(0, 0, 0));
// draw text!
matrix.setCursor(1, 0);
matrix.setTextSize(1);
matrix.setTextColor(matrix.Color333(7,0,0));
}
int fenge(String str,String fen,int index)
{
int weizhi;
String temps[str.length()];
int i=0;
do
{
weizhi = str.indexOf(fen);
if(weizhi != -1)
{
temps[i] = str.substring(0,weizhi);
str = str.substring(weizhi+fen.length(),str.length());
i++;
}
else {
if(str.length()>0)
temps[i] = str;
}
}
while(weizhi>=0);
if(index>i)return "-1";
return temps[index].toInt();
}
String Mystr = "";//声明字符串变量
void loop() {
if (Serial.available() > 0)
{ Mystr=Serial.readString();
if(Mystr=="B"){
matrix.fillScreen(matrix.Color333(0, 0, 0));
}
else{
int num=fenge(Mystr,",",0);
for(int i=1;i<=num-1;i=i+2){
int pose0=31-fenge(Mystr,",",i);
int pose1=fenge(Mystr,",",i+1);
matrix.drawPixel(pose0,pose1, matrix.Color333(7, 7, 7));
}
}
Mystr=="";
}
}
6. DEMO
The article was first published on https://mc.dfrobot.com.cn/, April 11, 2023
Cr: https://mc.dfrobot.com.cn/thread-315889-1-1.html
Author: 云天