Ciao a tutti sono Nicolò, recentemente ho sviluppato un piccolo cubesat 1U solo via software e prima di mandarlo in stampa sto facendo alcuni test per capire come strutturare il software di questo.
Sto riscontrando un problema nella parte di trasmissione di file in UART tra due arduino.
Il mio obbiettivo è quello di trasmettere un file contenuto in una micro SD a un'altro arduino il quale lo salverà in una micro SD.
Ho usato chatgpt e ho letto sui vari forum come trasmettere i file e sono arrivato a questi codici, il file lo trasmette ma quando lo apro dal pc oltre ad essere senza peso il file non viene riconosciuto.
MASTER - invia il file presente sulla SD
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
#define SD_CS 10 // Pin Chip Select della microSD
#define BUFFER_SIZE 64 // Dimensione del buffer
SoftwareSerial Serial1(7, 6); // TX, RX
void setup() {
Serial.begin(115200);
Serial1.begin(115200);
while (!Serial);
delay(500);
Serial.println("Inizializzazione...");
if (!SD.begin(SD_CS)) {
Serial.println("Errore nella microSD!");
return;
}
Serial.println("In attesa del ricevitore...");
unsigned long startTime = millis();
bool receivedResponse = false;
while (millis() - startTime < 10000) { // Attendi fino a 10 secondi
while (Serial1.available()) {
char response = Serial1.read();
if (response == 'R') { // Il ricevitore invia 'R' per indicare "READY"
Serial.println("Ricevitore pronto, avvio trasmissione...");
receivedResponse = true;
break;
}
}
if (receivedResponse) break;
}
if (!receivedResponse) {
Serial.println("Errore: nessuna risposta valida dal ricevitore.");
return;
}
sendFile("test.png");
}
void sendFile(const char* filename) {
File file = SD.open(filename);
if (!file) {
Serial.println("Errore nell'apertura del file!");
return;
}
Serial1.println("START"); // Segnala l'inizio della trasmissione
delay(100);
uint8_t buffer[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = file.read(buffer, BUFFER_SIZE)) > 0) {
Serial1.write(buffer, bytesRead);
Serial.write(buffer, bytesRead);
delay(10);
}
Serial1.println("END"); // Segnala la fine del file
file.close();
Serial.println("File inviato con successo!");
}
void loop() {}
SALVE - salva il file nella SD
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
#define SD_CS 10 // Pin Chip Select della microSD
#define BUFFER_SIZE 64 // Dimensione del buffer
SoftwareSerial Serial1(7,6);
void restart(){};
void setup() {
Serial.begin(115200);
Serial1.begin(115200);
while (!Serial);
delay(500);
Serial.println("Init");
if (!SD.begin(SD_CS)) {
Serial.println("Errore nell'inizializzazione della microSD!");
restart();
}
Serial.println("Pronto per ricevere il file...");
while (true) { // Continua a inviare "READY" fino a quando non riceve "START"
Serial1.write('R'); // Invia 'R' per indicare che è pronto
delay(1000);
while (Serial1.available()) {
char received = Serial1.read();
if (received == 'S') { // Ricevuto "START"
Serial.println("Ricezione in corso...");
receiveFile();
return;
}
}
}
}
void receiveFile() {
File file = SD.open("ricevuto.png", FILE_WRITE);
if (!file) {
Serial.println("Errore nella creazione del file!");
return;
}
uint8_t buffer[BUFFER_SIZE];
int bufferIndex = 0;
bool receiving = true;
while (receiving) {
while (Serial1.available()) {
char receivedChar = Serial1.read();
buffer[bufferIndex++] = receivedChar;
if (bufferIndex >= BUFFER_SIZE) { // Scrive sul file quando il buffer è pieno
file.write(buffer, BUFFER_SIZE);
Serial.write(buffer,BUFFER_SIZE);
bufferIndex = 0;
}
/*if(receivedChar == NULL){
receiving = false;
}*/
}
}
}
void loop() {}
Se qualcuno riesce a darmi una mano o consigliarmi una libreria che posso usare per trasmettere file di ogni genere da arduino lo ringrazio in anticipo!
Quel protocollo mi pare veramente degno di un codice di ChatGPT, ossia come al solito uno spunto ma che va sempre preso con le molle e verificato.
Per prima cosa: di quale Arduino parliamo? Perché SoftwareSerial generalmente è affidabile per velocità fino a 38400, a 115200 baud non l'ho mai visto funzionare correttamente, almeno su UNO R3, e Mega.
In particolare poi, a proposito del protocollo, vedo che il "trasmittente" manda la stringa "START" (seguita da CR e LF, ossia "\r\n") mentre il ricevente inizia a ricevere i dati appena vede il carattere 'S'... Ma tu nella Sd del destinatario hai provato ad aprire il file con un editor esadecimale? Secondo me i primi byte sono "TART\r\n" seguiti dal vero contenuto, col risultato che il file jpg viene "sminchiato".
Consiglio: fino a che non hai sufficiente pratica di programmazione, lascia perdere chatGPT (tranne solo come "spunto" magari per imparare qualcosa), che non impari una mazza.
... e che, nel 90% dei casi, di primo acchito produce codice che è sbagliato
Se uno conosce bene la materia se n'accorge e comincia a punzecchiarlo fino a quando non ammette l'errore e, piano piano, si avvicina a qualche cosa di decente, ma altrimenti ... un disastro.
Buongiorno e benvenuto nella sezione Italiana del forum,
cortesemente, come prima cosa, leggi attentamente il REGOLAMENTOdi detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazioneNELL'APPOSITA DISCUSSIONE (... quello che vedi in blu è un link, fai click su di esso per raggiungere la discussione) spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.
Senza entrare in troppi dettagli, ma solo ad una seconda occhiata (ma li avevo già visti alla prima):
Usi la seriale software ad una velocità eccessiva, 115200 non andrà mai
Non superare 19200 e ringrazia che vada
Per velocità maggiori passa a una scheda che abbia due seriali HW oppure evita di usare la USB e usa la sola seriale HW che hai
Lo handshaking (ovvero il reciproco riconoscimento e sincronizzazione) tra trasmettitore e ricevitore è molto approssimato ad esempio tu per cominciare la trasmissione trasmetti "START", ma in ricezione ti accontenti di una S maiuscola
E le 4 lettere che avanzano? Vanno a finire nel file?
Non hai un controllo degli errori
Ma soprattutto non chiudi il file alla fine (anzi, come la riconosci la fine?)
Per ispirazione prova a cercare le implementazioni in Arduino dei protocolli Xmodem, Ymodem e Zmodem
Dubito che facciano al caso tuo, a partire dal fatto che trasmettono blocchi troppo lunghi per una povera UNO, ma possono ispirare....
E perché dovrei farlo?
Se conosco la materia o faccio da solo e non chiedo alle AI oppure chiedo e poi correggo da me
Comunque dopo che ho ottenuto un risultato "certamente" non lo vado a spiegare alla AI, che impara a mie spese e rivende ad altri il mio lavoro
grazie per il consiglio, gli darò un occhiata. come scheda sto usando un arduino nano per fare dei test, e sul satellite sarà presente lo stesso microcontrollore un atmega328p e per prendere le immagini c'è un rp2040 con una camera ov5640. La obc è presente il atmega328p e avrà come sistema operativo freertos perchè dovrà eseguire delle operazioni in remoto. sulla scheda che gestisce le comunicazioni a terra non è presente una microsd quindi i passaggi che dovrà fare l'immagine
dalla microsd collegata all'RP2040 --> alla SD dell'OBC --> tramite la scheda radio a terra
ho fatto una prova, una funzione per tenere il tempo, una per eseguire i comandi che arrivano dal modulo radio e gestire le operazioni in remoto e ce la fa. le altre schede avranno un codice abbastanza semplice se vengono interpellate rispondono. magari posso usare simplecli per gestire le varie funzioni di queste
si certo, la obc (on board computer) è quella scheda all'interno di un satellite che gestisce tutte le operazioni e le comunicazioni con la terra. praticamente decide come muovere il satellite se le batterie sono scariche per orientare i pannelli solari (ma questa parte nel mio sistema la delocalizzo alla EPS eletric power supply)
Ciao io ho sviluppato un piccolo codice di prova che invia i dati dalla seriale di Arduino minima R4 alla SD, si basa nell'utilizzo dei caratatteri XOFF/XON e con l`ausilio di teraterm si inviano i dati dal PC divisi a pacchetti di 256byte.
/*
*Questo programma testato su Arduino Minima R4 consete di traferire tramite la UART
*qalsiasi file su SD. Usa teratem File>Sendfile>Binary>block 256/512>delay 1ms
*WorkInProgress 2025-01
*/
#include <SPI.h>
#include <SD.h>
#define CS_SD 10 // Pin Chip Select per la SD
#define BUFFER_SIZE 256 // Buffer da 512 byte per SD
#define XON 0x11 // ASCII DC1
#define XOFF 0x13 // ASCII DC3
File file;
char buffer[BUFFER_SIZE];
int bufferIndex = 0;
bool receiving = false;
unsigned long lastWriteTime = 0;
unsigned long totalBytesWritten = 0;
unsigned long totalBlocksWritten = 0;
void setup() {
Serial.begin(115200);
while (!Serial) {}
Serial.println("Inizializzazione SD...");
if (!SD.begin(CS_SD)) {
Serial.println(" Errore SD! Controlla i collegamenti.");
return;
}
Serial.println("SD pronta!");
if (SD.exists("output.bin")) {
SD.remove("output.bin");
Serial.println("File esistente 'output.bin' cancellato.");
}
Serial.write(XON); // Iniziamo il trasferimento
}
void loop() {
if (Serial.available()) {
if (!receiving) {
Serial.write(XOFF); // Ferma il flusso dati
file = SD.open("output.bin", FILE_WRITE);
if (!file) {
Serial.println("Errore apertura file!");
return;
}
Serial.println("Scrittura su SD iniziata...");
receiving = true;
}
while (Serial.available() && bufferIndex < BUFFER_SIZE) {
buffer[bufferIndex++] = Serial.read();
}
if (bufferIndex == BUFFER_SIZE) {
file.write((uint8_t*)buffer, BUFFER_SIZE);
totalBytesWritten += BUFFER_SIZE;
totalBlocksWritten++;
Serial.print(" Scritti ");
Serial.print(BUFFER_SIZE);
Serial.print(" byte - Blocco #");
Serial.println(totalBlocksWritten);
bufferIndex = 0;
lastWriteTime = millis();
}
Serial.write(XON); // Riprendiamo la trasmissione
}
// Aspetta 1 secondo dall'ultima scrittura prima di chiudere il file
if (receiving && Serial.available() == 0 && bufferIndex > 0 && millis() - lastWriteTime >= 4000) {
Serial.print("Ultimo bufferIndex prima della scrittura finale: ");
Serial.println(bufferIndex);
file.write((uint8_t*)buffer, bufferIndex);
totalBytesWritten += bufferIndex;
totalBlocksWritten++;
Serial.print("Scritti ultimi ");
Serial.print(bufferIndex);
Serial.println(" byte!");
bufferIndex = 0;
delay(5000);//debug
file.close();
Serial.println(" File salvato come 'output.bin'!");
Serial.print(" Totale blocchi scritti: ");
Serial.println(totalBlocksWritten);
Serial.print(" Totale byte scritti: ");
Serial.println(totalBytesWritten);
receiving = false;
}
}
Ora sto lavorando ed ho quasi completato una implementazione con SPI-NOR, se qualcuno è interessato potrei condividerlo in uno nuovo post, vi metto qui l`immagine del menu che sto implementando: