[Risolto] Connessione tra arduino e VsualBasic con socket

Buon giorno a tutti
scrivo a voi esperti per chiedere un aiuto per quanto riguarda un progetto su cui sono fermo.
In pratica il progetto consiste nell'avere un Arduino Uno con scheda ethernet connesso tramite IP fisso ad una rete locale ed un pc connesso alla stessa maniera su cui gira un software scritto in Visual Basic 2010. Il software all'accadere di un evento dovrebbe inviare una piccola stringa tramite socket ad Arduino che è già programmato per rispondere tramite il controllo di relè.
Ora l'Arduino si connette alla rete (ho provato tramite CMD da un pc ad eseguire un controllo con l'istruzione 'ping' e risulta connesso) il problema è che il programma in VB non riesce a connettersi alla scheda Arduino tramite socket.
Ho provato in tutti i modi che conosco ma non sono riuscito a fare gran che e avrei bisogno di un aiuto.
Posto di seguito i codici dei due programmi.

Arduino:

#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008

//Dichiarazione dei pin di controllo
#define S 7
#define C 8
#define A 9
#define lEmergenza 11
//Dichiarazione dei pin di controllo dei led di stato
#define lOn 4
#define lOff 3
//Dichiarazione dei pin di controllo dei sensori
#define sA 12
//Dichiarazione pin interruttore analogico luce
#define Button 13

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 26);
byte subnet[] = {255, 255, 255, 0};
byte gateway[] = {192, 168, 1, 1};
IPAddress ipRem(192, 168, 1, 2);

unsigned int localPort = 7272;      // local port to listen on
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  //buffer to hold incoming packet,
//char  ReplyBuffer[] = "acknowledged";       // a string to send back
EthernetUDP Udp;

char last = '0';
//char codice[UDP_TX_PACKET_MAX_SIZE];
boolean oldState;

void setup() {
  // start the Ethernet and UDP:
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  Udp.begin(localPort);
  Serial.begin(9600);
    //Inizializzazione dei pin di controllo
  pinMode(S, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(A, OUTPUT);
  pinMode(lOn, OUTPUT);
  pinMode(lOff, OUTPUT);
  pinMode(lEmergenza, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  //Impostazione iniziale delle uscite
  digitalWrite(S, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(A, LOW);
  digitalWrite(lOn, LOW);
  digitalWrite(lOff, LOW);
  //Inizializzazione dei pin di controllo dei sensori
  pinMode(sensoreArmadio, INPUT);
  pinMode(Button, INPUT);
  oldState = false;

}

void loop() {
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    IPAddress remote = Udp.remoteIP();
    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    //codice = packetBuffer;

      if (Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE) == '1') {
        digitalWrite(S, LOW);
        digitalWrite(lOn, HIGH);
      }
      if (Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE) == '0') { //codice
        digitalWrite(S, HIGH);
        digitalWrite(lOn, LOW);
      }
  
      if (Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE) == '2') { //codice
        digitalWrite(C, LOW);
        digitalWrite(lOff, HIGH);
      }
      if (Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE) == '4') { //codice
        digitalWrite(C, HIGH);
        digitalWrite(lOff, LOW);
      }
      
      if (Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE) == '3') { //codice
        digitalWrite(A, LOW);
      }
      if (Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE) == '5') { //codice
        digitalWrite(A, HIGH );
      }
  
      if (sA == HIGH){
        digitalWrite(A, LOW);
        if (last != 'a'){
          Udp.beginPacket(ipRem, localPort);
          Udp.write("a");
          Udp.endPacket();
          last = 'a';
        }
      }else{
        digitalWrite(A, HIGH);
        if (last != 'b'){
          Udp.beginPacket(ipRem, localPort);
          Udp.write("b");
          Udp.endPacket();
          last = 'b';
        }
      }
  }
  delay(10);
}

Visual Basic:

Imports System.Net
Imports System.Net.Sockets
Imports System.Text

Public Class Camera
    Dim statoLScriv As Boolean
    Dim statoLCamera As Boolean
    Dim statoLArmad As Boolean

    'Indirizzi IP e MAC per comunicazione ethernet
    Dim host As IPAddress = Nothing
    Dim ethSocket As Socket = Nothing

    Private Sub Camera_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'SerialPort1.PortName = "COM4"
        'SerialPort1.Open()
        statoLScriv = False
        statoLCamera = False
        statoLArmad = False

        If IPAddress.TryParse("192.168.1.26", host) Then
            'Creazione IPEndPoint e Socket
            Dim ep As IPEndPoint = New IPEndPoint(host, 7272)
            ethSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            'Connessione Socket  Integer.Parse("7272")
            ethSocket.Connect(ep)
    
        End If
    End Sub

    Private Sub lScrivOn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lScrivOn.Click
        If SerialPort1.IsOpen Then
            If (statoLScriv = False) Then
                SerialPort1.Write("1")
                If ethSocket.Connected Then
                    'Invio i byte del messaggio
                    ethSocket.Send(Encoding.ASCII.GetBytes("1"))
                End If
                statoLScriv = True
                lScrivOn.BackColor = Color.Silver
                lScrivOff.BackColor = Color.LightGray
            End If
        End If
    End Sub

    Private Sub lScrivOff_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lScrivOff.Click
        If SerialPort1.IsOpen Then
            If (statoLScriv = True) Then
                SerialPort1.Write("0")
                If ethSocket.Connected Then
                    'Invio i byte del messaggio
                    ethSocket.Send(Encoding.ASCII.GetBytes("0"))
                End If
                statoLScriv = False
                lScrivOff.BackColor = Color.Silver
                lScrivOn.BackColor = Color.LightGray
            End If
        End If
    End Sub

    Private Sub lCameraOn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lCameraOn.Click
        If SerialPort1.IsOpen Then
            'If (statoLCamera = False) Then
            SerialPort1.Write("2")
            If ethSocket.Connected Then
                'Invio i byte del messaggio
                ethSocket.Send(Encoding.ASCII.GetBytes("2"))
            End If
            statoLCamera = True
            lCameraOn.BackColor = Color.Silver
            lCameraOff.BackColor = Color.LightGray
            'End If
        End If
    End Sub

    Private Sub lCameraOff_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lCameraOff.Click
        If SerialPort1.IsOpen Then
            'If (statoLCamera = True) Then
            SerialPort1.Write("4")
            If ethSocket.Connected Then
                'Invio i byte del messaggio
                ethSocket.Send(Encoding.ASCII.GetBytes("4"))
            End If
            statoLCamera = False
            lCameraOff.BackColor = Color.Silver
            lCameraOn.BackColor = Color.LightGray
            'End If
        End If
    End Sub

    Private Sub lArmadioOn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lArmadioOn.Click
        If SerialPort1.IsOpen Then
            If (statoLArmad = False) Then
                SerialPort1.Write("3")
                If ethSocket.Connected Then
                    'Invio i byte del messaggio
                    ethSocket.Send(Encoding.ASCII.GetBytes("3"))
                End If
                statoLArmad = True
                lArmadioOn.BackColor = Color.Silver
                lArmadioOff.BackColor = Color.LightGray
            End If
        End If
    End Sub

    Private Sub lArmadioOff_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lArmadioOff.Click
        If SerialPort1.IsOpen Then
            If (statoLArmad = True) Then
                SerialPort1.Write("5")
                If ethSocket.Connected Then
                    'Invio i byte del messaggio
                    ethSocket.Send(Encoding.ASCII.GetBytes("5"))
                End If
                statoLArmad = False
                lArmadioOff.BackColor = Color.Silver
                lArmadioOn.BackColor = Color.LightGray
            End If
        End If
    End Sub

End Class

Vi ringrazio in anticipo e spero di essermi spiegato bene.
Buona giornata :slight_smile:

Quale shield ethernet ? la WIZ5100 ufficiale o la più economica ENC28J60 ?

Sto usando la scheda ENC28J60

tommy1000:
Ho provato in tutti i modi che conosco ma non sono riuscito a fare gran che e avrei bisogno di un aiuto.
Posto di seguito i codici dei due programmi.

Scusa, ma nel codice qui vedo qualcosa che non capisco.
Stando a quanto mi sembra di vedere tu mandi pacchetti composti da un solo byte/carattere, esatto?
Ma qui tu fai:

void loop() {
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    IPAddress remote = Udp.remoteIP();
    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    //codice = packetBuffer;

      if (Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE) == '1') {
        digitalWrite(S, LOW);
        digitalWrite(lOn, HIGH);
      }
      if (Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE) == '0') { //codice
        digitalWrite(S, HIGH);
        digitalWrite(lOn, LOW);
      }
  ... eccetera

La read() legge un pacchetto dal suo buffer UDP e lo registra nel buffer che gli passi. Quindi perché richiami la read() più volte? Tu leggi il pacchetto, se presente, con UNA sola read(), e poi analizzi il pacchetto in base al tuo formato e dimensione massima.
Io in altro progetto ho fatto una funzioncina per leggere UN pacchetto:

bool udpReceive(void)
{
  int packetSize = udp.parsePacket();
  if(packetSize) {
    // read the packet into packetBufffer
    udp.read(pkt,IRS_PACKET_SIZE);
    return true;
  } else
    return false;
}

quindi nel tuo loop farai una cosa del tipo:

   ...
  if ( udpReceive() ) {
    switch (pkt[0]) {
      case '0':
        // Quello che devo fare per '0'
        break;
      case '1':
        // Quello che devo fare per '1'
        break;
... eccetera...

Secondo me @docdoc ha centrato il tuo errore nel codice.
E' come fare int c=Serial.read(); ed invece di testare il valore di c fare altre if di nuovo usando Serial.read

Grazie mille ad entrambi per l'aiuto,
Ora che ho corretto il codice di Arduino ho verificato che il problema sta però nel codice VB perché questo metodo di invio:

ethSocket.Send(Encoding.ASCII.GetBytes("1"))

converte il carattere in ascii quindi io dovrei poi riconvertirlo in decimale una volta ricevuto per poter avere un giusto risultato facendo i confronti con if (o switch).
Avreste per caso un consiglio su come potrei fare?
Grazie ancora e buona serata

Buona sera a tutti
Dopo numerosi tentativi ho deciso di passare al protocollo TCP che ha funzionato un paio di volte.
Un nuovo problema è sorto quando ho aggiunto uno schermo LCD, da quel momento (anche caricando i vecchi sketch e rimuovendo lo schermo) la scheda non si connette più alla rete locale (provato tramite ping) quindi non l'SW in Visual Basic non può connettersi.
Qualcuno sarebbe così gentile da dare un'occhiata al sorgete di seguito per capire se ho fatto qualche clamoroso errore?
Grazie in anticipo per l'attenzione.

#include <Dhcp.h>
#include <Dns.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <util.h>

#include <LiquidCrystal.h>

//Dichiarazione dei pin di controllo delle luci
#define lScriv 7
//Dichiarazione dei pin di controllo dei sensori
#define sensoreArmadio 5
//Dichiarazione pin interruttore analogico luce
#define Button 2

//byte mac[] = {0x90,0xA2,0xDA,0x00,0x23,0x5D};
byte mac[] = {0x90, 0xa2, 0xda, 0x00, 0xd1, 0x4b};
IPAddress ip(192, 168, 1, 100);
//byte subnet[] = {255, 255, 255, 0};
IPAddress subnet(255, 255, 255, 0);
IPAddress gateway(192, 168, 1, 1);
IPAddress ipRem(192, 168, 1, 2);
EthernetServer server = EthernetServer(70);

String buffer = "";
String codice = "";
char last = '0';
boolean oldState;

LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);

void setup() {
  //Apertura connessione ethernet, seriale e lcd
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  //Ethernet.begin(mac, ip);////NON FUNZIONA////
  Serial.begin(9600);
  server.begin();
  lcd.begin(16, 2);
  
  //Inizializzazione dei pin di controllo delle luci
  pinMode(lScriv, OUTPUT);
   pinMode(LED_BUILTIN, OUTPUT);
  //Impostazione iniziale delle uscite
  digitalWrite(lScriv, HIGH);
   //Inizializzazione dei pin di controllo dei sensori
  pinMode(Button, INPUT);
  oldState = false;
  lcd.print("Something");
}

void loop() {
  EthernetClient client = server.available();
  if (client){ 
    while (client.connected()){
      if (client.available()){
        codice = ((String)client.read());
        Serial.print(codice);
        Serial.print(" - ");
        buffer+=codice;

      if (codice == "49") {//1
        digitalWrite(lScriv, LOW);
      }
    }
}
  delay(10);
}

Tommaso

Salve a tutti
dopo un lungo periodo di pausa ho ripreso in mano il progetto decidendo di cambiare completamente la scheda ethernet e sembra funzionare tutto alla grande.
Grazie a tutti e scusate l'imprevisto

Tommaso