Skip to content

Commit 5166ada

Browse files
added usb support feature
1 parent 17ca2a7 commit 5166ada

File tree

7 files changed

+271
-183
lines changed

7 files changed

+271
-183
lines changed

examples/Twin_CodeLab/Twin_CodeLab.ino

Lines changed: 120 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
/*
2-
Twin_CodeLab v2.4.3
2+
Twin_CodeLab v2.5.0
33
44
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.
55
66
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+
!!! COK ONEMLI !!!: Tools sekmesinden USB CDC on Boot seçeneği "Enabled" olarak seçilmelidir. (USB ile kod çalıştırabilmek için gereklidir)
79
810
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.
911
1012
https://github.com/twin-science-robotics/hw_twin_aiot_module_arduino_library
1113
12-
24 Eylül 2025
14+
09 Ekim 2025
1315
Twin Science & Robotics
1416
1517
*/
@@ -18,6 +20,9 @@
1820
#include "BLEManager.h"
1921
#include "CommandHandler.h"
2022

23+
SemaphoreHandle_t serialMutex;
24+
SemaphoreHandle_t canSendPacketSemaphore;
25+
2126
// Modüle güç verildiğinde beliren Twin Science logo animasyonu
2227
uint8_t twinlogo[][8]= {
2328
{0x38, 0x44, 0xBA, 0x82, 0xBA, 0x44, 0x38, 0x00}, // Orijinal
@@ -36,37 +41,21 @@ QueueHandle_t patternQueue;
3641
portMUX_TYPE ledmatrix_mux = portMUX_INITIALIZER_UNLOCKED;
3742
// Modül setup
3843
void setupTwin_F() {
39-
40-
41-
4244
pinMode(D6_output_pin, OUTPUT); // D6
43-
4445
pinMode(D9_output_pin, OUTPUT); // D6
45-
4646
pinMode(D10_output_pin, OUTPUT); // D6
4747

4848
pinMode(S1pin, OUTPUT);
4949
pinMode(S2pin, OUTPUT);
5050
pinMode(S3pin, OUTPUT);
5151

5252
pinMode(D_IN_4, INPUT);
53-
54-
5553
pinMode(D_IN_8, INPUT);
56-
57-
5854
pinMode(D_IN_12, INPUT);
59-
60-
6155
pinMode(AN_IN_4, INPUT);
62-
63-
6456
pinMode(AN_IN_8, INPUT);
65-
66-
6757
pinMode(AN_IN_12, INPUT);
6858

69-
7059
pinMode(latchPin, OUTPUT);
7160
pinMode(clockPin, OUTPUT);
7261
pinMode(dataPin, OUTPUT);
@@ -76,16 +65,17 @@ void setupTwin_F() {
7665

7766
FastLED.addLeds<WS2812B,RGB_PIN , RGB>(leds, 1);
7867
FastLED.setBrightness(64);
79-
8068
}
8169

8270
BLEManager bleManager;
8371
CommandHandler commandHandler;
8472

85-
QueueHandle_t bleQueue;
73+
QueueHandle_t commandQueue;
8674
QueueHandle_t responseQueue;
8775

88-
channel_st bleChannel;
76+
channel_st channel;
77+
volatile bool isUsbConnected = false;
78+
8979
CRGB leds[NUM_LEDS];
9080

9181
// Bluetooth ile alınan veriler işlenir
@@ -95,28 +85,121 @@ void processingTask(void *pvParameters) {
9585
const TickType_t xFrequency = pdMS_TO_TICKS(10);
9686

9787
while(1) {
98-
if (xQueueReceive(bleQueue, &receivedCmd, pdMS_TO_TICKS(100)) == pdTRUE) {
99-
commandHandler.handleCommand(receivedCmd);
88+
if (xQueueReceive(commandQueue, &receivedCmd, pdMS_TO_TICKS(10)) == pdTRUE) { //portMAX_DELAY
89+
commandHandler.handleCommand(receivedCmd);
10090
}
10191
vTaskDelayUntil(&xLastWakeTime, xFrequency);
10292
}
10393
}
10494

95+
void sendUSB(const Packet& packet) {
96+
if (xSemaphoreTake(canSendPacketSemaphore, (TickType_t)0) == pdTRUE) {
97+
if (xSemaphoreTake(serialMutex, portMAX_DELAY) == pdTRUE) {
98+
uint8_t packet_length = packet.data[4] + header_length;
99+
Serial.write(packet.data, packet_length);
100+
xSemaphoreGive(serialMutex);
101+
}
102+
}
103+
else {
104+
//Serial.println("Semaphore alınamadı, paket gönderilemedi.");
105+
}
106+
}
107+
105108
// Veri işlendikten sonra cevap dönülür (sensör verileri gibi)
106109
void responseTask(void *pvParameters) {
107110
Packet packet;
108111
TickType_t xLastWakeTime = xTaskGetTickCount();
109-
const TickType_t xFrequency = pdMS_TO_TICKS(10);
112+
const TickType_t xFrequency = pdMS_TO_TICKS(5);
110113

111114
while(1) {
112115
vTaskDelayUntil(&xLastWakeTime, xFrequency);
113116

114-
if (xQueueReceive(responseQueue, &packet, pdMS_TO_TICKS(10)) == pdTRUE) {
115-
bleManager.sendResponse(packet);
117+
if (xQueueReceive(responseQueue, &packet, pdMS_TO_TICKS(5)) == pdTRUE) {
118+
if(packet.source == CHAN_BLE)
119+
bleManager.sendResponse(packet);
120+
else if(packet.source == CHAN_USB) sendUSB(packet);
116121
}
117122
}
118123
}
119124

125+
bool readPacketFromSerial(Packet& packet) {
126+
// 1. Senkronizasyon baytını bekle
127+
// readBytesUntil gibi bir fonksiyonla ilk senkron baytını arayabiliriz,
128+
// ama basitlik için bayt bayt okuma daha nettir.
129+
while (Serial.available() > 0 && Serial.read() != SYNC_BYTE1){
130+
vTaskDelay(pdMS_TO_TICKS(5));
131+
}
132+
133+
// Seri portta yeterli veri yoksa veya ilk bayt bulunamadıysa çık
134+
if (Serial.available() < (header_length - 1)) {
135+
return false;
136+
}
137+
138+
// 2. Başlığın geri kalanını oku
139+
uint8_t header[header_length];
140+
header[0] = SYNC_BYTE1; // İlkini zaten bulduk
141+
size_t read_count = Serial.readBytes(&header[1], header_length - 1);
142+
143+
if (read_count != (header_length - 1)) {
144+
// Beklenen başlık uzunluğu okunamadı, hata.
145+
return false;
146+
}
147+
148+
// 3. Başlığı doğrula
149+
if (header[1] != SYNC_BYTE2 || header[2] != SYNC_BYTE3) {
150+
// Senkronizasyon baytları yanlış, bu geçerli bir paket değil.
151+
return false;
152+
}
153+
154+
// 4. Veri uzunluğunu al ve veriyi oku
155+
uint8_t payload_length = header[4];
156+
157+
// Başlığı pakete kopyala
158+
memcpy(packet.data, header, header_length);
159+
160+
if (payload_length > 0) {
161+
if (Serial.available() < payload_length) {
162+
// Verinin tamamı henüz gelmemiş, bir sonraki döngüde tekrar deneriz.
163+
// Not: Bu basit yaklaşımda yarım paketler atılır. Daha gelişmiş bir yapı
164+
// state machine ile durumu koruyabilir. Ama çoğu durumda bu yeterlidir.
165+
return false;
166+
}
167+
// Veriyi başlığın hemen arkasına oku
168+
read_count = Serial.readBytes(&packet.data[header_length], payload_length);
169+
if (read_count != payload_length) {
170+
// Veri okunurken bir sorun oldu.
171+
return false;
172+
}
173+
}
174+
175+
// Paket başarıyla ve tamamen okundu
176+
return true;
177+
}
178+
179+
180+
void usbTask(void *pvParameters) {
181+
Packet usbPacket;
182+
183+
while(1) {
184+
185+
if (Serial.available() >= header_length) {
186+
187+
memset(&usbPacket, 0, sizeof(Packet));
188+
if (readPacketFromSerial(usbPacket)) {
189+
// Geçerli bir paket okundu, kuyruğa gönder
190+
usbPacket.source = CHAN_USB;
191+
isUsbConnected = true;
192+
xSemaphoreGive(canSendPacketSemaphore);
193+
if (xQueueSendToBack(commandQueue, &usbPacket, 0) != pdTRUE) {
194+
// Kuyruk dolu, hata yönetimi
195+
// Serial.println("usbqueue error");
196+
}
197+
}
198+
}
199+
200+
vTaskDelay(pdMS_TO_TICKS(20)); //yogun haberlesmede sorun olursa 10ms test edilebilir
201+
}
202+
}
120203
// Led matrixi yenileyen fonksiyon
121204
void ledMatrixTask(void *pvParameters) {
122205

@@ -177,7 +260,7 @@ void connTask(void *pvParameters) {
177260
while(1) {
178261

179262
vTaskDelayUntil(&xLastWakeTime, xFrequency);
180-
currentConnectionState = bleManager.isConnected();
263+
currentConnectionState = bleManager.isConnected()|| isUsbConnected;
181264
//Serial.println(currentConnectionState);
182265

183266
if(currentConnectionState != prevConnectionState) {
@@ -200,7 +283,7 @@ void bleblinkTask(void *pvParameters) {
200283

201284
while(1) {
202285

203-
if(bleManager.isConnected() == false){
286+
if(!bleManager.isConnected() && !isUsbConnected){
204287
//Serial.println("led is on");
205288

206289
leds[0] = CRGB(0,0,255);
@@ -226,7 +309,7 @@ void scrollIDTask(void *pvParameters) {
226309

227310
while(1) {
228311

229-
if(bleManager.isConnected() == false){
312+
if(!bleManager.isConnected() && !isUsbConnected){
230313

231314
scrollID(offset);
232315
offset++;
@@ -298,16 +381,16 @@ void scrollID(int offset){
298381

299382

300383
void setup() {
301-
//Serial.begin(115200);
302-
303-
384+
Serial.begin(9600);
304385
// Kuyrukları oluştur
305-
bleQueue = xQueueCreate(QUEUE_LENGTH, sizeof(Packet));
386+
commandQueue = xQueueCreate(QUEUE_LENGTH, sizeof(Packet));
306387
responseQueue = xQueueCreate(QUEUE_LENGTH, sizeof(Packet));
307388
patternQueue = xQueueCreate(QUEUE_LENGTH, sizeof(Packet));
308-
moduleName = calculateModuleName() ;
389+
serialMutex = xSemaphoreCreateMutex();
390+
canSendPacketSemaphore = xSemaphoreCreateBinary();
309391

310-
//Setups
392+
moduleName = calculateModuleName() ;
393+
//Setups
311394
bleManager.setup(moduleName);
312395
setupTwin_F();
313396
commandHandler.initTwin_F();
@@ -317,11 +400,10 @@ void setup() {
317400
xTaskCreate(responseTask, "ResponseTask", 4096, NULL, 3, NULL);
318401
xTaskCreate(ledMatrixTask, "ledmatrixTask", 4096, NULL, 1, NULL);
319402
LogoAnimate();
403+
xTaskCreate(usbTask, "USBTask", 4096, NULL, 1, NULL);
320404
xTaskCreate(connTask, "ConnectionTask", 4096, NULL, 1, NULL);
321405
xTaskCreate(bleblinkTask, "bleblinkTask", 4096, NULL, 1, NULL);
322406
xTaskCreate(scrollIDTask, "scrollIDTask", 4096, NULL, 1, NULL);
323-
324-
325407
//Serial.println(moduleName);
326408
}
327409

@@ -383,3 +465,4 @@ String calculateModuleName() {
383465
return "Twin " + colorNames[modVal / 36] + colorNames[(modVal % 36) / 6] + colorNames[modVal % 6];
384466
}
385467

468+

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=Twin_AIoT
2-
version=1.0.8
2+
version=1.1.0
33
author=TwinScience
44
55
sentence=A library containing example codes for Twin AIoT module.

src/BLEManager.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ void BLEManager::setup(const String& moduleName) {
2020

2121
//BLEDevice::setMTU(23);
2222

23-
pCharacteristic->setCallbacks(new MyCharacteristicCallbacks(bleQueue));
23+
pCharacteristic->setCallbacks(new MyCharacteristicCallbacks(commandQueue));
2424
pCharacteristic->addDescriptor(new BLE2902());
2525
pCharacteristic->setValue("0");
2626
pService->start();
@@ -81,7 +81,8 @@ void BLEManager::MyCharacteristicCallbacks::onWrite(BLECharacteristic *pChar) {
8181
if(value.length() > 0) {
8282
size_t copyLength = min(value.length(), sizeof(cmd.data));
8383
memcpy(cmd.data, value.c_str(), copyLength);
84-
if (xQueueSendToBack(bleQueue, &cmd, 0) != pdTRUE) {
84+
cmd.source = CHAN_BLE;
85+
if (xQueueSendToBack(commandQueue, &cmd, 0) != pdTRUE) {
8586
//Serial.println("blequeue error");
8687
}
8788
//vTaskDelayUntil(&xLastWakeTime, xFrequency);

src/BLEManager.h

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,6 @@
77
#include <BLE2902.h>
88
#include "Constants.h"
99

10-
struct message_st {
11-
uint8_t message_length ;
12-
uint8_t message_id ;
13-
uint8_t message_data[data_length];
14-
};
15-
16-
struct channel_st {
17-
message_st received;
18-
message_st sent;
19-
};
20-
21-
struct Packet {
22-
uint8_t data[packet_size];
23-
};
24-
25-
2610
class BLEManager {
2711
public:
2812
BLEManager();
@@ -55,8 +39,8 @@ class BLEManager {
5539
};
5640

5741
extern BLEManager bleManager;
58-
extern channel_st bleChannel;
59-
extern QueueHandle_t bleQueue;
42+
extern channel_st channel;
43+
extern QueueHandle_t commandQueue;
6044
extern QueueHandle_t responseQueue;
6145

6246

0 commit comments

Comments
 (0)