Skip to content

Commit a43e3ef

Browse files
added Codelab firmware
1 parent 903a468 commit a43e3ef

14 files changed

+4253
-1
lines changed
Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
/*
2+
Twin_CodeLab
3+
4+
Bu yazılım Twin CodeLab Web (https://code.twinscience.com/) ya da mobil uygulamaları ile blok kodlama yapabilme imkanı sunan yazılımdır.
5+
6+
Arduino IDE üzerinden Twin AIoT modülüne gömülen herhangi bir arduino kodundan sonra Twin Codelab ile blok kodlama yapmak isterseniz bu yazılımı yükleniz gereklidir.
7+
8+
Temel olarak bu kod Twin Codelab uygulamalarını çalıştıran donanımlar (bilgisayar, tablet, telefon vb) ile Twin AIoT modülü arasında, Bluetooth bağlantısı üzerinden veri alışverişi yapar ve blok kodlarını çalıştırır.
9+
10+
https://github.com/twin-science-robotics/hw_twin_aiot_module_arduino_library
11+
12+
30 Ağustos 2025
13+
Twin Science & Robotics
14+
15+
*/
16+
#include <Arduino.h>
17+
#include "Constants.h"
18+
#include "BLEManager.h"
19+
#include "CommandHandler.h"
20+
21+
// Modüle güç verildiğinde beliren Twin Science logo animasyonu
22+
uint8_t twinlogo[][8]= {
23+
{0x38, 0x44, 0xBA, 0x82, 0xBA, 0x44, 0x38, 0x00}, // Orijinal
24+
{0x00, 0x38, 0x44, 0xBA, 0x82, 0xBA, 0x44, 0x38}, // Aşağı
25+
{0x00, 0x1C, 0x22, 0x5D, 0x41, 0x5D, 0x22, 0x1C}, // Sağa
26+
{0x1C, 0x22, 0x5D, 0x41, 0x5D, 0x22, 0x1C, 0x00}, // Yukarı
27+
{0x38, 0x44, 0xBA, 0x82, 0xBA, 0x44, 0x38, 0x00}, // Sola (başlangıç)
28+
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
29+
};
30+
31+
32+
// Modül ismi (örnek : Twin RGB)
33+
String moduleName;
34+
35+
QueueHandle_t patternQueue;
36+
portMUX_TYPE ledmatrix_mux = portMUX_INITIALIZER_UNLOCKED;
37+
// Modül setup
38+
void setupTwin_F() {
39+
40+
41+
42+
pinMode(D6_motor_pin, OUTPUT); // D6
43+
44+
pinMode(D9_motor_pin, OUTPUT); // D6
45+
46+
pinMode(D10_motor_pin, OUTPUT); // D6
47+
48+
pinMode(S1pin, OUTPUT);
49+
pinMode(S2pin, OUTPUT);
50+
pinMode(S3pin, OUTPUT);
51+
52+
pinMode(D_IN_4, INPUT);
53+
54+
55+
pinMode(D_IN_8, INPUT);
56+
57+
58+
pinMode(D_IN_12, INPUT);
59+
60+
61+
pinMode(AN_IN_4, INPUT);
62+
63+
64+
pinMode(AN_IN_8, INPUT);
65+
66+
67+
pinMode(AN_IN_12, INPUT);
68+
69+
70+
pinMode(latchPin, OUTPUT);
71+
pinMode(clockPin, OUTPUT);
72+
pinMode(dataPin, OUTPUT);
73+
74+
pinMode(TRIG_PIN, OUTPUT);
75+
pinMode(ECHO_PIN, INPUT);
76+
77+
FastLED.addLeds<WS2812B,RGB_PIN , RGB>(leds, 1);
78+
FastLED.setBrightness(64);
79+
80+
}
81+
82+
BLEManager bleManager;
83+
CommandHandler commandHandler;
84+
85+
QueueHandle_t bleQueue;
86+
QueueHandle_t responseQueue;
87+
88+
channel_st bleChannel;
89+
CRGB leds[NUM_LEDS];
90+
91+
// Bluetooth ile alınan veriler işlenir
92+
void processingTask(void *pvParameters) {
93+
Packet receivedCmd;
94+
TickType_t xLastWakeTime = xTaskGetTickCount();
95+
const TickType_t xFrequency = pdMS_TO_TICKS(10);
96+
97+
while(1) {
98+
if (xQueueReceive(bleQueue, &receivedCmd, pdMS_TO_TICKS(100)) == pdTRUE) {
99+
commandHandler.handleCommand(receivedCmd);
100+
}
101+
vTaskDelayUntil(&xLastWakeTime, xFrequency);
102+
}
103+
}
104+
105+
// Veri işlendikten sonra cevap dönülür (sensör verileri gibi)
106+
void responseTask(void *pvParameters) {
107+
Packet packet;
108+
TickType_t xLastWakeTime = xTaskGetTickCount();
109+
const TickType_t xFrequency = pdMS_TO_TICKS(10);
110+
111+
while(1) {
112+
vTaskDelayUntil(&xLastWakeTime, xFrequency);
113+
114+
if (xQueueReceive(responseQueue, &packet, pdMS_TO_TICKS(10)) == pdTRUE) {
115+
bleManager.sendResponse(packet);
116+
}
117+
}
118+
}
119+
120+
// Led matrixi yenileyen fonksiyon
121+
void ledMatrixTask(void *pvParameters) {
122+
123+
uint8_t buffer[8] = {0};
124+
125+
TickType_t xLastWakeTime;
126+
const TickType_t xFrequency = pdMS_TO_TICKS(10);
127+
128+
xLastWakeTime = xTaskGetTickCount();
129+
130+
//uint8_t brightness = 15;
131+
//uint16_t onTime = (brightness + 1) * 16; // 16-256 mikrosaniye
132+
133+
while(1) {
134+
135+
if (xQueueReceive(patternQueue, &buffer,0) != pdTRUE) {
136+
//error
137+
138+
}
139+
140+
for (int row = 0; row < 8; row++) {
141+
uint8_t patternRow = buffer[row];
142+
uint8_t reversedPattern = commandHandler.reverseBits(patternRow);
143+
uint8_t rowData = (1 << row);
144+
uint8_t colData = ~reversedPattern;
145+
146+
portENTER_CRITICAL(&ledmatrix_mux);
147+
commandHandler.shiftOutAll(colData, rowData);
148+
portEXIT_CRITICAL(&ledmatrix_mux);
149+
150+
vTaskDelay(pdMS_TO_TICKS(1));
151+
//delayMicroseconds(190);
152+
153+
portENTER_CRITICAL(&ledmatrix_mux);
154+
commandHandler.shiftOutAll(0x00, 0x00);
155+
portEXIT_CRITICAL(&ledmatrix_mux);
156+
//vTaskDelay(pdMS_TO_TICKS(1));
157+
//delayMicroseconds(10);
158+
159+
}
160+
161+
162+
163+
vTaskDelayUntil(&xLastWakeTime, xFrequency);
164+
//vTaskDelay(pdMS_TO_TICKS(5));
165+
166+
}
167+
}
168+
169+
// Bluetooth bağlantı durumunu periyodik olarak kontrol eden fonksiyon
170+
void connTask(void *pvParameters) {
171+
TickType_t xLastWakeTime = xTaskGetTickCount();
172+
const TickType_t xFrequency = pdMS_TO_TICKS(1000);
173+
174+
bool prevConnectionState = false;
175+
bool currentConnectionState = false;
176+
177+
while(1) {
178+
179+
vTaskDelayUntil(&xLastWakeTime, xFrequency);
180+
currentConnectionState = bleManager.isConnected();
181+
//Serial.println(currentConnectionState);
182+
183+
if(currentConnectionState != prevConnectionState) {
184+
if(currentConnectionState){
185+
//Serial.println("device connected");
186+
commandHandler.initTwin_F();
187+
}
188+
else {
189+
//Serial.println("disconnected");
190+
commandHandler.initTwin_F();
191+
}
192+
193+
prevConnectionState = currentConnectionState;
194+
}
195+
}
196+
}
197+
198+
// Bluetooth bağlantı durumunu RGB led'de belirten fonksiyon
199+
void bleblinkTask(void *pvParameters) {
200+
201+
while(1) {
202+
203+
if(bleManager.isConnected() == false){
204+
//Serial.println("led is on");
205+
206+
leds[0] = CRGB(0,0,255);
207+
FastLED.show();
208+
vTaskDelay(pdMS_TO_TICKS(500));
209+
//Serial.println("led is off");
210+
leds[0] = CRGB(0,0,0);
211+
FastLED.show();
212+
vTaskDelay(pdMS_TO_TICKS(500));
213+
214+
}
215+
216+
217+
vTaskDelay(pdMS_TO_TICKS(80));
218+
}
219+
220+
}
221+
222+
// Modül ismini led matrixde kaydıran fonksiyon
223+
void scrollIDTask(void *pvParameters) {
224+
225+
int offset = 0;
226+
227+
while(1) {
228+
229+
if(bleManager.isConnected() == false){
230+
231+
scrollID(offset);
232+
offset++;
233+
234+
}
235+
236+
237+
vTaskDelay(pdMS_TO_TICKS(80)); // scroll speed
238+
}
239+
240+
}
241+
242+
243+
void scrollID(int offset){
244+
245+
String scrollText = " " + moduleName;
246+
uint8_t textLen = scrollText.length();
247+
const int charWidth = 8;
248+
const int gapWidth = 0;
249+
250+
int compositeLength = textLen * (charWidth + gapWidth);
251+
252+
uint8_t compositePattern[compositeLength] = {0};
253+
int pos = 0;
254+
255+
for (size_t i = 0; i < textLen && pos < compositeLength; i++) {
256+
char c = scrollText[i];
257+
const uint8_t* letterPattern = getPatternForLetter(c);
258+
for (int col = 0; col < charWidth && pos < compositeLength; col++) {
259+
uint8_t colByte = 0;
260+
for (int row = 0; row < 8; row++) {
261+
if (letterPattern[row] & (1 << (7 - col))) {
262+
colByte |= (1 << row);
263+
}
264+
}
265+
compositePattern[pos++] = colByte;
266+
}
267+
268+
for (int g = 0; g < gapWidth && pos < compositeLength; g++) {
269+
compositePattern[pos++] = 0x00;
270+
}
271+
}
272+
273+
const int displayWidth = 8;
274+
275+
uint8_t window[8];
276+
277+
for (int i = 0; i < displayWidth; i++) {
278+
window[i] = compositePattern[(offset + i) % compositeLength];
279+
280+
}
281+
uint8_t rowData[8] = {0};
282+
for (int r = 0; r < 8; r++) {
283+
uint8_t rowByte = 0;
284+
for (int c = 0; c < 8; c++) {
285+
uint8_t bit = (window[c] >> r) & 1;
286+
rowByte |= (bit << (7 - c));
287+
}
288+
rowData[r] = rowByte;
289+
}
290+
if (xQueueSendToBack(patternQueue, &rowData, pdMS_TO_TICKS(10)) != pdTRUE) {
291+
//Serial.println("id queue error");
292+
}
293+
294+
295+
296+
}
297+
298+
299+
300+
void setup() {
301+
//Serial.begin(115200);
302+
303+
304+
// Kuyrukları oluştur
305+
bleQueue = xQueueCreate(QUEUE_LENGTH, sizeof(Packet));
306+
responseQueue = xQueueCreate(QUEUE_LENGTH, sizeof(Packet));
307+
patternQueue = xQueueCreate(QUEUE_LENGTH, sizeof(Packet));
308+
moduleName = calculateModuleName() ;
309+
310+
//Setups
311+
bleManager.setup(moduleName);
312+
setupTwin_F();
313+
commandHandler.initTwin_F();
314+
315+
// Görevleri oluştur
316+
xTaskCreate(processingTask, "ProcessingTask", 4096, NULL, 3, NULL);
317+
xTaskCreate(responseTask, "ResponseTask", 4096, NULL, 3, NULL);
318+
xTaskCreate(ledMatrixTask, "ledmatrixTask", 4096, NULL, 1, NULL);
319+
LogoAnimate();
320+
xTaskCreate(connTask, "ConnectionTask", 4096, NULL, 1, NULL);
321+
xTaskCreate(bleblinkTask, "bleblinkTask", 4096, NULL, 1, NULL);
322+
xTaskCreate(scrollIDTask, "bleblinkTask", 4096, NULL, 1, NULL);
323+
324+
325+
//Serial.println(moduleName);
326+
}
327+
328+
void loop() {
329+
vTaskDelete(NULL);
330+
}
331+
332+
//Twin logo animasyonu
333+
void LogoAnimate(){
334+
335+
uint8_t numFrames = 6 ;
336+
337+
for(uint8_t i = 0; i<numFrames ; i++){
338+
if (xQueueSendToBack(patternQueue, &twinlogo[i], pdMS_TO_TICKS(10)) != pdTRUE) {
339+
//Serial.println("logo queue error");
340+
}
341+
342+
vTaskDelay(pdMS_TO_TICKS(300)); // approximately 2 sec animation
343+
}
344+
345+
}
346+
347+
348+
const uint8_t* getPatternForLetter(char c) {
349+
350+
for (size_t i = 0; i < numLetters; i++) {
351+
if (ledMatrixLetters[i].letter == c) {
352+
return ledMatrixLetters[i].pattern;
353+
}
354+
}
355+
return ledMatrixLetters[numLetters - 1].pattern;
356+
}
357+
358+
359+
// Unique name calculation on mac address
360+
String calculateModuleName() {
361+
uint64_t mac = ESP.getEfuseMac();
362+
363+
//Serial.print("MAC Address: ");
364+
//Serial.println(mac);
365+
366+
uint8_t macBytes[6];
367+
368+
for (int i = 0; i < 6; i++) {
369+
macBytes[i] = (mac >> (8 * i)) & 0xFF;
370+
}
371+
372+
uint16_t sum = 0;
373+
for (int i = 0; i < 6; i++) {
374+
sum += macBytes[i];
375+
}
376+
377+
uint16_t modVal = sum % 216;
378+
//Serial.print("Mod Value (sum % 216): ");
379+
//Serial.println(modVal);
380+
381+
String colorNames[] = {"R", "G", "B", "W", "O", "P"};
382+
383+
return "Twin " + colorNames[modVal / 36] + colorNames[(modVal % 36) / 6] + colorNames[modVal % 6];
384+
}
385+

library.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
name=Twin_AIoT
2-
version=1.0.3
2+
version=1.0.4
33
author=TwinScience
44
55
sentence=A library containing example codes for Twin AIoT module.
66
paragraph=This library is used for ESP32-S3 based custom board designed by TwinScience
77
category=Device Control
8+
depends=ESP32Servo (=3.0.6), FastLED (=3.9.14)
89
url= https://github.com/twin-science-robotics/hw_twin_aiot_module_arduino_library
910
architectures=esp32

0 commit comments

Comments
 (0)