Comunicazione con PC (C#) tramite USB

Salve a tutti
vi pongo un primo problema per il mio progetto, Chiaramente mi manca tanta conoscenza su Arduino e quindi abbiate pazienza.
Devo far accendere dei led su Arduino due (in questo caso ho provato su Arduino Uno e il problema è identico) tramite dei comandi da PC con un programma fatto in C#

per fare un esempio può semplice ho creato appositamente due righe di codice per capire se è un mio errore o la logica di Arduino è fatta così:

unsigned long tempoAttuale = 0;
unsigned long tempoPrecedente = 0;
String rx;

void setup() {
  pinMode(5, OUTPUT);
  pinMode(7, OUTPUT);
  Serial.begin(57600);
}

void loop() {
  tempoAttuale = millis();
  if (tempoAttuale > tempoPrecedente + 10) 
  {
    digitalWrite(7, LOW);

    if (Serial.available() > 0)  
    {
      digitalWrite(7, HIGH);
      rx = Serial.readString();
      
      if (rx.equals("off")) 
      {
        digitalWrite(5, HIGH);
      }
      if (rx.equals("on")) 
      {
        digitalWrite(5, LOW);
      }
    }
    tempoPrecedente = millis();
  }
}

Poi su PC, in C# ho inserito una sola form e un pulsante (button1) . il codice è il seguente :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace prova_arduino_test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        bool sr;
        private void button1_Click(object sender, EventArgs e)
        {
            string DatoInviato;

            if (sr)
            {
                sr = false;
                DatoInviato = "on";
            }
            else
            {
                sr= true;
                DatoInviato = "off";
            }
            serialPort1.Write(DatoInviato);
        }
        private void Form1_Load(object sender, EventArgs e)
        {
                serialPort1.PortName = "COM9";
                try
                {
                    serialPort1.Open();
                }
                catch
                {
                    MessageBox.Show("Errore sulla porta!",
                    "Controllo scheda Arduino", MessageBoxButtons.OK);
                }
            }
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            serialPort1.Close();
        }
    }
}

in pratica il led sull'uscita 7 evidenzia che Arduino riceve un segnale sulla seriale e l'uscita 5 accende e spegne in alternanza.
Quello che non è normale è che non sono "sincronizzati" e attende un tempo che non è modificabile (ho messo un ritardo di 10ms, ma se metto di più non cambia niente) .

Video che visualizza il comportamento

ciao adf69

daal reference di arduino:

Serial.readString()

Description

Serial.readString() reads characters from the serial buffer into a String. The function terminates if it times out (see setTimeout()).

Serial.readString() inherits from the Stream utility class.

e

Serial.setTimeout()

Description

Serial.setTimeout() sets the maximum milliseconds to wait for serial data. It defaults to 1000 milliseconds.

Serial.setTimeout() inherits from the Stream utility class.

Syntax

Serial.setTimeout(time)

se cerchi qui nel forum l'uso della classe String è sconsigliata per tutta una serie di motivi, legati alla gestione della memoria del micro, e si consiglia invece l'uso delle stringhe classiche del C (array di char) o l'implementazione di semplici protocolli di scambio dati...carattere di inizio, messaggio, carattere di terminazione/controllo.

grazie, risolto perfettamente.
La questione stringa era solo per semplificare l'esempio.

questo è il codice che ho utilizzato, si, gli esperti sicuramente lo potrebbero migliorare molto :smile:

unsigned long tempoAttuale = 0;
unsigned long tempoPrecedente = 0;

char arr[36];
char Dati[36];
int MaxLed = 10;
int cnt = 0;
int val = 0;
int Led = 0;
int Nr;
char c;
int x;
bool DatiOk;

void setup() {
  pinMode(5, OUTPUT);
  pinMode(7, OUTPUT);
  Serial.begin(57600);
  Serial.setTimeout(100);
}

void loop() {

  RecuperaDatidaSeriale();

  if (DatiOk) {
    for (Nr = 0; Nr < MaxLed; Nr++ )
    {
      Led = Nr + 5;             // 0 = per poter scalare sui pin
      Serial.print(Led);        // numero del PIN usato

      if (Dati[Nr] == '0') {    // Spegne
        Serial.print(" Spento");
        digitalWrite(Led, LOW);
      }
      if (Dati[Nr] == '1') {    // Accende
        Serial.print(" Acceso");
        digitalWrite(Led, HIGH);
      }
      if (Dati[Nr] == '2') {    // Lampeggia lento
        Serial.print(" Lamp. Lento");
        digitalWrite(Led, LOW);
      }
      if (Dati[Nr] == '3') {    // Lampeggia veloce
        Serial.print(" Lamp. Veloce");
        digitalWrite(Led, LOW);
      }
      if (Dati[Nr] == '4') {    // Lampeggia Velocissimo
        Serial.print(" Lamp. Velocissimo");
        digitalWrite(Led, LOW);
      }
      Serial.println();
      DatiOk = LOW;
    }
  }
}


void RecuperaDatidaSeriale()
{
  tempoAttuale = millis();
  if (tempoAttuale > tempoPrecedente + 100)
  {
    if (Serial.available())
    {
      c = Serial.read();
      if (c == '\n' or c == '#') // verifica se il dato è stato inviato
      {
        if (cnt == MaxLed)  // verifica se sono arrivato i giusti caratteri
        {

          Serial.print("ok ricevuto tutti i ");
          Serial.print(MaxLed);
          Serial.println(" caratteri");

          DatiOk = HIGH;
          for (x = 0; x < MaxLed ; x++) // trasposta i caratteri in un altra array pulita
          {
            Dati[x] = arr[x];
            cnt = 0;
          }
        }
        else if (cnt < MaxLed)
        {
          Serial.print("non ho ricevuto tutti i caratteri, ne vanno inviati ");
          Serial.println(MaxLed);
          AzzeraArray();
        }

        if (cnt > MaxLed)
        {
          Serial.print("ho ricevuto troppi caratteri, ne vanno inviati ");
          Serial.println(MaxLed);
          AzzeraArray();
        }
      }
      else {
        arr[cnt] = c;  // assegna valore alla array
        cnt = cnt + 1; // e aumenta contatore
      }
    }
  }
}

void AzzeraArray()
{
  for (x = 0; x < MaxLed ; x++)  // assegna 0 a tutti i dati della array
  {
    arr[x] = 0;
  }
  cnt = 0;
  DatiOk = LOW;
  Serial.println("cancellato tutto");
}

poi in c# il dato inviato sarà con questo formato: DatoInviato = "0111111111#"
Chiaramente le Serial.print sono solo per verifica nel monitor seriale.

adesso passo alla perché comunicazione Arduino > PC, sicuramente chiederò altri spunti.

Grazie

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.