Oppure

Loading
28/03 11:39
nightwolf
ok, ho capito quello che vuoi dire, ma in visual basic come avverrebbe tutto ciò? ho fatto la conversione del codice e nell output c'è solo la divisione della stringa, non riceve niente da arduino. l ho tradotto così se è giusto
 Shared esempio As String() = New String() {"-322.54;50-322.30", ";50-322.30;", "50-322.20;"}


e poi dentro timer2

 Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
        Prova()
    End Sub
    Private Shared Sub Prova()
        Dim rn As Random = New Random()
        Dim lettura As String = esempio(rn.[Next](0, esempio.Length))
        Dim ln As String() = lettura.Split("-"c)
        Dim val As String = ln.Where(Function(x) x.Contains(";")).FirstOrDefault()
        Dim val2 As String() = val.Split(";"c)
        Dim bussola As Integer = 0
        Dim potenziometro As Integer = 0

        If val2.Length = 2 Then

            If val2(0).Length > 1 AndAlso val2(1).Length > 1 Then
                Integer.TryParse(val2(0).Split("."c)(0), bussola)
                Integer.TryParse(val2(1), potenziometro)
                Console.WriteLine("Bussola Vale: " & bussola)
                Console.WriteLine("Potenziometro Vale:" & potenziometro)
            End If
        End If
    End Sub

e nell output viene fuori
Bussola Vale: 50
Potenziometro Vale: 322

mentre tornando a l vecchio codice ho provato ad abbassare l intervall di timer2 a 500 e 250, e niente, stesso errore. ho prvato anche a portare il delay di arduino che prima era a 300 di portarlo a 500 come timer2, ed è lo stesso errore.
aaa
28/03 13:46
Carlo
Postato originariamente da nightwolf:
mentre tornando a l vecchio codice ho provato ad abbassare l intervall di timer2 a 500 e 250, e niente, stesso errore. ho prvato anche a portare il delay di arduino che prima era a 300 di portarlo a 500 come timer2, ed è lo stesso errore.


Per non mescolare, con me eravamo al punto della listbox1 con i valori ricevuti con questo codice:
SOLUZIONE 2)
Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
          Dim str As String = RiceviDati()
     
           str = str.Replace(vbCrLf, "\n")
           ListBox1.Items.Add(DateTime.Now.ToLongTimeString & " - str = " & str)
           ListBox1.TopIndex = ListBox1.Items.Count - 1
           ListBox1.HorizontalScrollbar = True
End Sub


Regolando la temporizzazione non sei mai riuscito ad ottenere una lista di valori decenti?
Mi posti la foto con Timer2.Interval = 300?

SOLUZIONE 3)
Tutte le soluzioni proposte sicuramente possono essere ottimizzate e fatte funzionare... ma se si vuole instaurare una comunicazione sicura il Timer2 in VB va eliminato e bisogna attivare l'evento che si scatena quando la seriale riceve i dati, rendendo la comunicazione sincrona.

La prima cosa da fare è dichiarare la seriale con WithEvents:
Dim serialport1 As New SerialPort ' vecchia dichiarazione da modificare
Dim WithEvents serialport1 As New SerialPort ' modificata


a questo punto invece di Timer2 che va a leggere a caso:
Private Sub serialport_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles serialport1.DataReceived
        Dim sp As SerialPort = DirectCast(sender, SerialPort)
        Dim str As String = sp.ReadExisting() ' Legge tutti i dati presenti nel buffer di input
        str = str.Replace(vbCrLf, "\n") ' se ci fossero degli accapo li rende visibili
        ListBox1.Items.Add(DateTime.Now.ToLongTimeString & " - str = " & str) ' ora di ricezione
        ListBox1.TopIndex = ListBox1.Items.Count - 1 ' rende visibile l'ultima riga
        ListBox1.HorizontalScrollbar = True
End Sub


In questo modo arduino ogni volta che invia dati sulla seriale, vengono letti in VB.
Modificando il delay su arduino VB resta sincronizzato.

Mi posti la foto della ListBox1 anche con questo codice?

Il codice è ancora solo per testare la comunicazione, solo dopo che nella ListBox1 riceverai i dati corretti aggiungeremo il codice VB per la bussola e il potenziometro con l'eliminazione dei dati non congrui.

Ultima modifica effettuata da Carlo 28/03 14:20
in programmazione tutto è permesso
28/03 14:00
Thejuster
@carlo
Potrebbe essere un'idea quella di fare un override direttamente sulla comunicazione.

Ma ho teorizzato dopo che si, in alcuni casi, arduino possa inviare stringhe non sempre corrette.
Parliamo sempre di arduino un pò come un giocattolo e non preciso come un PLC.
basta veramente poco per mandarlo fuori fase.

La mia soluzione era basata sul controllo diretto della striga per verificare se esattamente esistono tutti i dati
alle loro rispettive posizioni, altrimenti ignora la chiamata attuale, andando alla successiva.

Ma nightwolf ha confuso completamente :rotfl:


@nightwolf

Hai usato

Shared esempio As String() = New String() {"-322.54;50-322.30", ";50-322.30;", "50-322.20;"}



E solo un esempio!!!


dovresti cambiare questa



 Dim lettura As String = esempio(rn.[Next](0, esempio.Length))



la variabile lettura deve contenere ciò che legge dalla seriale.
Il resto lo fà la funzione.
La funzione controlla se la riga è strutturata in modo corretto con

-Bussola;Potenziometro.

Se rispecchia questa struttura, splitta i dati e ne controlla i valori.
Se anche uno di quei valore è errato, prosegue fin quando non trova una riga corretta
che contenga esattamente valori come esempio

-Bussola;Potenziometro
-350.22;50

tutto qua. deve funzionare per forza.

Questo link
dotnetfiddle.net/…

Simula una lettura di arduino dando a caso appunto seguendo l'esempio, valori misti.
Errati e buoni.
Quando la funzione riceve la stringa strutturata correttamente, ne ricava i valori.
Altrimenti l'output è vuoto.
Prova premendo ripetutamente su esegui. e noterai che alcune volte funziona altre no.
Appunto perché scrive solo quando la stringa è ricevuta in modo corretto
o che contenga almeno in parte quello che serve per poterla leggere.

Conclusione


If val2(0).Length > 1 AndAlso val2(1).Length > 1 Then
                Integer.TryParse(val2(0).Split("."c)(0), bussola)
                Integer.TryParse(val2(1), potenziometro)
                
                 'Invece di usare Console.WriteLine, devi associare le variabili ai vari controlli
                 'Variabile bussola per la bussola
                 'Variabile potenziometro per il potenziometro fine

                'Console.WriteLine("Bussola Vale: " & bussola)
                'Console.WriteLine("Potenziometro Vale:" & potenziometro)
            End If



Ho scritto nei commenti cosa dovresti fare da li.
la variabile bussola contiene i gradi letti dalla stringa stessa cosa per la variabile potenziometro.
Devi semplicemente assegnare il valore delle variabili ai controlli fine.
Ultima modifica effettuata da Thejuster 28/03 14:12
mire.forumfree.it/ - Mire Engine
C# UI Designer
28/03 14:11
Carlo
Postato originariamente da Thejuster:
Ma ho teorizzato dopo che si, in alcuni casi, arduino possa inviare stringhe non sempre corrette.


Concordo, infatti la ListBox1 serve per vedere cosa si riceve e solo dopo aver valutato i possibili errori, intervenire con il codice.

La verifia se il dato è numerico e nel range previsto dovrebbe essere sufficiente.

@ nightwolf, vai a vedere la mia risposta: delle 14:46 Giovedì, 28/03/2024
Ultima modifica effettuata da Carlo 28/03 16:12
in programmazione tutto è permesso
28/03 23:23
nightwolf
buonasera a tutti, allora, mettondo il timer2.interval=300 e scrivendo il questo codice
 Function RiceviDati() As String
        Dim Ricevuti As String
        Try
            Ricevuti = SerialPort1.ReadExisting
            If Ricevuti = Nothing Then
                Return "E;null" ' ritorna con la E
            Else
                Return Ricevuti
            End If
        Catch ex As Exception
            Return "E;" & ex.Message ' ritorna con la E
        End Try
    End Function

ho la prima foto
aaa
28/03 23:25
nightwolf
sostituendo readExisting con serialport1.readline
ho invece la seconda foto
aaa
28/03 23:29
nightwolf
dopo un po, e svariati tentativi ho provato a scrivere questo
 Dim str As String = RiceviDati()

        str = str.Replace(vbCrLf, "\n")
        ListBox1.Items.Add(DateTime.Now.ToLongTimeString & " - str = " & str)
        ListBox1.TopIndex = ListBox1.Items.Count - 1
        ListBox1.HorizontalScrollbar = True

        If str = "" Then Return
        ' Tolgo l'eventuale "\r"
        str = Replace(str, "\r", "")
        ' Elaboro la stringa
        Dim valoriDivisi() As String = str.Split(";")
        If valoriDivisi(0) = "E" Then
            lblgradi.Text = "errore"
            ' in valoriDivisi(1) ' il tipo d'errore da mostrare dove vuoi
        Else
            ' Il primo dato è riferito ai gradi della bussola
            valoriDivisi(0) = valoriDivisi(0).Replace(".", ",") ' se ci fosse il punto decimale viene sostituito con la virgola decimale
            avanzamento = CInt(valoriDivisi(0))
            lblgradi.Text = avanzamento.ToString("000°")
            Pcboxbussola.Invalidate()

        End If


e la bussola ha iniziato a funzionare. adesso rimane soltante il volume, che se aggiungo la parte restante del codice mi da sempre l errore sulla stringa.
aaa
28/03 23:37
nightwolf
contrordine ho aggiunto il resto del codice ma l errore che mi dava era su di una parte di codice non dichiarata, e più precisamente non riusciva a trovare
video.Wmp1.settings.voume = video.Volume_control1.value

ma solamente perchè mancava la L in volume. ho aggiusto
video.Wmp1.settings.volume = video.Volume_control1.value

adeso anche il volume ha iniziato a funzionare in parte, cioè si attiva la prima volta ma dopo smette di attivarsi. questo è il codice completo
Imports System.IO.Ports
Imports System.Drawing.Drawing2D
Public Class principale
    Dim bussola As Image = New Bitmap("bussola.png") ' bmp in ram dal file originale, deve esistere nella cartelle dell'eseguibile
    Dim destinazione As Integer
    Dim avanzamento As Integer
    Dim direzione As Integer
    Dim cX As Integer = bussola.Width \ 2
    Dim cY As Integer = bussola.Height \ 2
    Dim dX As Integer = bussola.Width
    Dim dY As Integer = bussola.Height
    Dim vel As Integer = 2 ' velocità, valori supportati 1, 2, 3, 5, 6, 9, 10 (divisibili per 90)

    Private Sub principale_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.CenterToParent()
        btnconnetti.Enabled = False
        btnChiudi.Enabled = False
        cmbbaund.SelectedItem = "9600"

        media_pleyer.Timer5.Start()
    End Sub

    Private Sub btnscanport_Click(sender As Object, e As EventArgs) Handles btnscanport.Click
        cmbPorte.Items.Clear()
        Dim myPort As Array
        Dim i As Integer
        myPort = IO.Ports.SerialPort.GetPortNames
        cmbPorte.Items.AddRange(myPort)
        i = cmbPorte.Items.Count
        i = i - i
        Try
            cmbPorte.SelectedIndex = i

        Catch ex As Exception
            Dim result As DialogResult
            result = MessageBox.Show("com port non trovata", "Attenzione !!!", MessageBoxButtons.OK)
            cmbPorte.Text = ""
            cmbPorte.Items.Clear()
            Call principale_Load(Me, e)
        End Try
        btnconnetti.Enabled = True
        cmbPorte.DroppedDown = True
    End Sub

    Private Sub btnconnetti_Click(sender As Object, e As EventArgs) Handles btnconnetti.Click
        If cmbPorte.Text <> "" Then
            Try
                btnconnetti.Enabled = False
                SerialPort1.BaudRate = cmbbaund.SelectedItem
                SerialPort1.PortName = cmbPorte.SelectedItem
                SerialPort1.Open()
                btnChiudi.Enabled = True
                Timer2.Start()
                lblConnessione.Text = "Connesso"
                lblConnessione.ForeColor = Color.Green
                Timerpanelincrease.Enabled = True
            Catch ex As Exception
                MsgBox("errore:" & ex.Message, MsgBoxStyle.Critical)
            End Try
        End If

    End Sub

    Private Sub btnChiudi_Click(sender As Object, e As EventArgs) Handles btnChiudi.Click
        btnChiudi.Enabled = False
        SerialPort1.Close()
        btnconnetti.Enabled = True
        Timer1.Stop()
        Timer2.Stop()
        lblConnessione.Text = "Disconnesso"
        lblConnessione.ForeColor = Color.Red
        Timerpanelincrease.Enabled = True
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        If SerialPort1.BytesToRead > 0 Then
            Try
                Dim i As Single = SerialPort1.ReadExisting
                Console.WriteLine($"DATO: [{i}] ({i.ToString})")
                media_pleyer.lb_volume.Text = i.ToString + "%"
                media_pleyer.Volume_control1.value = i.ToString
                lb_volume.Text = i.ToString + "%"
                Volume_control1.value = i.ToString
                media_pleyer.Timer3.Start()
                media_pleyer.AxWindowsMediaPlayer1.settings.volume = media_pleyer.Volume_control1.value
                AxWindowsMediaPlayer1.settings.volume = media_pleyer.Volume_control1.value
            Catch ex As Exception

            End Try
        End If

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        media_pleyer.Show()
        Me.Hide()
        lb_title.Text = ""
        AxWindowsMediaPlayer1.Ctlcontrols.stop()
        AxWindowsMediaPlayer1.URL = ""
    End Sub

    Private Sub Timerpanelincrease_Tick(sender As Object, e As EventArgs) Handles Timerpanelincrease.Tick
        If Panel3.Height > 0 Then
            Panel3.Height -= 5
        Else
            Timerpanelincrease.Enabled = False
        End If
    End Sub

    Private Sub timerpanelreduce_Tick(sender As Object, e As EventArgs) Handles timerpanelreduce.Tick
        If Panel3.Height < 80 Then
            Panel3.Height += 5
        Else
            timerpanelreduce.Enabled = False
        End If
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        If Panel3.Height > 0 Then
            Timerpanelincrease.Enabled = True

        Else
            timerpanelreduce.Enabled = True

        End If
    End Sub

    Private Sub Btn_105_Click(sender As Object, e As EventArgs) Handles Btn_105.Click
        AxWindowsMediaPlayer1.URL = "https://icy.unitedradio.it/Radio105.mp3"
        lb_title.Text = "Radio 105"
    End Sub

    Private Sub Btn_gamma_Click(sender As Object, e As EventArgs) Handles Btn_gamma.Click
        AxWindowsMediaPlayer1.URL = "https://rn2.fluidstream.eu/gammaradio.aac"
        lb_title.Text = "Gamma Radio"
    End Sub

    Private Sub Btn_r101_Click(sender As Object, e As EventArgs) Handles Btn_r101.Click
        AxWindowsMediaPlayer1.URL = "http://icecast.unitedradio.it/r101"
        lb_title.Text = "R101"
    End Sub

    Private Sub Btn_radioitalia_Click(sender As Object, e As EventArgs) Handles Btn_radioitalia.Click
        AxWindowsMediaPlayer1.URL = "https://radioitaliasmi.akamaized.net/hls/live/2093120/RISMI/stream01/streamPlaylist.m3u8"
        lb_title.Text = "Radio Italia Solo Musica Italiana"
    End Sub

    Private Sub Btn_kisskiss_Click(sender As Object, e As EventArgs) Handles Btn_kisskiss.Click
        AxWindowsMediaPlayer1.URL = "http://ice07.fluidstream.net:8080/KissKiss.mp3"
        lb_title.Text = "Radio Kiss Kiss"
    End Sub

    Private Sub Btn_Rds_Click(sender As Object, e As EventArgs) Handles Btn_Rds.Click
        AxWindowsMediaPlayer1.URL = "http://stream1.rds.it:8000/rds64k"
        lb_title.Text = "RDS"
    End Sub
    Dim x As Integer
    Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click

        If x = 0 Then
            PictureBox1.BackgroundImage = My.Resources.power_off
            SerialPort1.Write("A")
            x = 1
        Else
            PictureBox1.BackgroundImage = My.Resources.power_on
            SerialPort1.Write("O")
            x = 0
        End If
    End Sub

    Private Sub Pcboxbussola_Paint(sender As Object, e As PaintEventArgs) Handles Pcboxbussola.Paint
        e.Graphics.TranslateTransform(cX + Pcboxbussola.Width / 2 - cX, cY + Pcboxbussola.Height / 2 - cY) ' posizione centro
        e.Graphics.RotateTransform(avanzamento) ' rotazione in gradi
        e.Graphics.DrawImage(bussola, -cX, -cY, dX, dY) ' dimensione 100%
    End Sub
    Function RiceviDati() As String
        Dim Ricevuti As String
        Try
            Ricevuti = SerialPort1.ReadLine
            If Ricevuti = Nothing Then
                Return "E;null" ' ritorna con la E
            Else
                Return Ricevuti
            End If
        Catch ex As Exception
            Return "E;" & ex.Message ' ritorna con la E
        End Try
    End Function

    Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived


    End Sub

    Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
        Dim str As String = RiceviDati()

        str = str.Replace(vbCrLf, "\n")
        ListBox1.Items.Add(DateTime.Now.ToLongTimeString & " - str = " & str)
        ListBox1.TopIndex = ListBox1.Items.Count - 1
        ListBox1.HorizontalScrollbar = True

        If str = "" Then Return
        ' Tolgo l'eventuale "\r"
        str = Replace(str, "\r", "")
        ' Elaboro la stringa
        Dim valoriDivisi() As String = str.Split(";")
        If valoriDivisi(0) = "E" Then
            lblgradi.Text = "errore"
            ' in valoriDivisi(1) ' il tipo d'errore da mostrare dove vuoi
        Else
            ' Il primo dato è riferito ai gradi della bussola
            valoriDivisi(0) = valoriDivisi(0).Replace(".", ",") ' se ci fosse il punto decimale viene sostituito con la virgola decimale
            avanzamento = CInt(valoriDivisi(0))
            lblgradi.Text = avanzamento.ToString("000°")
            Pcboxbussola.Invalidate()
            ' Il dato in: valoriDivisi(1), è riferito al volume e è una stringa

            media_pleyer.lb_volume.Text = valoriDivisi(1) + "%"
            media_pleyer.Volume_control1.value = valoriDivisi(1)
            lb_volume.Text = valoriDivisi(1) + "%"
            Volume_control1.value = valoriDivisi(1)
            media_pleyer.Timer3.Start()
            media_pleyer.AxWindowsMediaPlayer1.settings.volume = media_pleyer.Volume_control1.value
            AxWindowsMediaPlayer1.settings.volume = media_pleyer.Volume_control1.value
            video.Wmp1.settings.volume = video.Volume_control1.value
        End If
    End Sub

End Class

aaa