Gå til innhold

parse seriell data i C#?


Anbefalte innlegg

Videoannonse
Annonse

Nå må du skrive ut bare når det feiler. Bruk try/catch rundt koden, og Console.WriteLine inne i Catch.

Begynn med å skrive ut hele stringen som kommer inn fra Arduino.

Mener du slik?

 private void displaydata_event(object sender, EventArgs e)
        {
            datetime = DateTime.Now;
            string time = datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
            time_text_box.Text = time;

            try
            {
                string[] sensorData = in_data.Split(new char[] { ' ', ' ' });
                List<string> tokens = new List<string>();
                foreach (string s in sensorData)
                {
                    if (s.Length != 0)
                    {
                        tokens.Add(s);
                    }
                }


                txtTemperature.Text = tokens[0];
                txtHumidity.Text = tokens[1];
                txtSoil_moisture.Text = tokens[2];

                int tmp1 = int.Parse(tokens[0]);

            }

            catch
            {
                Console.WriteLine(tokens.Count);
            }

        }
Lenke til kommentar

Ja. F.eks Console.WriteLine(tokens.Count + "   " + in_data);

Hei igjen Hårek, feilen ser ikke ut til å komme mer etter at jeg la inn try and catch kommandoene.

Jeg la inn følgende kode:

private void displaydata_event(object sender, EventArgs e)
        {
            datetime = DateTime.Now;
            string time = datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
            time_text_box.Text = time;

            string[] sensorData = in_data.Split(new char[] { ' ', ' ' });
            List<string> tokens = new List<string>();

            try
            {
                
                foreach (string s in sensorData)
                {
                    if (s.Length != 0)
                    {
                        tokens.Add(s);
                    }
                }


                txtTemperature.Text = tokens[0];
                txtHumidity.Text = tokens[1];
                txtSoil_moisture.Text = tokens[2];
                         
            }

            catch (Exception ex1)
            {
                Console.WriteLine(tokens.Count+""+in_data);
            }

        }

Hvis du legger merke, så har jeg tatt ut array sensorData og lista tokens ut av try og da ble feilmeldingen borte i forhold til not exist in current context.

En annen ting, jeg fikk flere ganger noen tall i Console vidnuet :

Kjøring 1:

223

 

 

 

 

Kjøring 2: 123

 

 

 

Kjøring 3:

 

223

2    19    0

 

Kjøring 4:

 

2     19   0

 

 

Andre ganger kom det ikke noe i Consoloe vinduet?

 

Hva tror du dette skyldes ?

Endret av Tesla1856
Lenke til kommentar

... så har jeg tatt ut array sensorData og lista tokens ut av try og da ble feilmeldingen borte i forhold til not exist in current context.

Det er riktig. Les om "nested scope" her: http://www.blackwasp.co.uk/CSharpVariableScopes.aspx

 

Jeg forstår ikke utskriften fra Console vindu, ser ikke hva som er hva.

Koden din er tokens.Count+""+in_data - det blir ikke noe mellomrom mellom dem med "". Bedre med tokens.Count+"   "+in_data

Du må skrive ut en noen linjer når det fungerer, så du har en referanse.

 

Du kan også legge Exception meldingen inn i utskriften:

Console.WriteLine(tokens.Count+"   "+in_data + "    " + ex1.Message);

Lenke til kommentar

Det er riktig. Les om "nested scope" her: http://www.blackwasp.co.uk/CSharpVariableScopes.aspx

 

Jeg forstår ikke utskriften fra Console vindu, ser ikke hva som er hva.

Koden din er tokens.Count+""+in_data - det blir ikke noe mellomrom mellom dem med "". Bedre med tokens.Count+"   "+in_data

Du må skrive ut en noen linjer når det fungerer, så du har en referanse.

 

Du kan også legge Exception meldingen inn i utskriften:

Console.WriteLine(tokens.Count+"   "+in_data + "    " + ex1.Message);

Ok, jeg har korrigert koden og lagt inn mellomrom.

I tillegg har jeg lagt inn linjen:

 Console.WriteLine(tokens.Count+" "+in_data+ " "+ex1.Message);

Når jeg kjørte programmet fikk jeg dette i Comsole vinduet:

 

1 21 Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
Lenke til kommentar

Da er in_data bare "21", og dermed bare 1 token. Da vil tokens[1] og tokens[2 feile.

Du kan komme unna problemet med 

if (tokens.Count >= 3) {
    txtTemperature.Text = tokens[0];
    txtHumidity.Text = tokens[1];
    txtSoil_moisture.Text = tokens[2];
}

Ellers bør du se på Arduino koden hvorfor det mangler data. 

Lenke til kommentar

Da er in_data bare "21", og dermed bare 1 token. Da vil tokens[1] og tokens[2 feile.

Du kan komme unna problemet med 

if (tokens.Count >= 3) {
    txtTemperature.Text = tokens[0];
    txtHumidity.Text = tokens[1];
    txtSoil_moisture.Text = tokens[2];
}

Ellers bør du se på Arduino koden hvorfor det mangler data. 

Hei igjken Hårek, 

Takk for mange gode tips  :) .

Jeg ønsker å gjøre en liten ting til i programmet. 

Jeg jobber jo med saken, med tar seff lang tid da jeg må lese meg opp på mye og søke om alt. 

Jeg ønsker å lage en klasse som jeg kaller en Sensor.cs klasse.

I tillegg ønsker jeg å lage en Alarm.cs klasse slik at jeg kan legge til en funksjonalitet der jeg får en lampe til å lyse rødt i Wondowsform når temperatur og fuktighet overskrider angitte nivåer.

 

Jeg har laget klassene, så jeg har startet jo. Dog jeg vet ikke om jeg må flytte en del av koden (der programmet mottar seriell data)  fra hoved programmet mitt og kalle en metode fra feks. Sensor klassen?

Jeg ve tliksom ikke hvordan jeg kan gjøre dette på best mulig måte?

Endret av Tesla1856
Lenke til kommentar

Jeg pleier å lage en "hovedklasse", og så lager den de andre klassene. De andre klassene får en referanse til hovedklassen ved behov, slik at de kan kommunisere. F.eks:

 

I "hovedklassen": alarm = new Alarm(this);

Alarm klassen:

 

private readonly MasterClass master;

 

Alarm(MasterClass master) {

    this.master = master;

    ...

}

 

Hvordan koden skal organiseres er noe man finner ut etter hvert, med erfaring. Man trenger ikke tenke på å lage den perfekte koden i første omgang. De fleste prosjekter vil modifiseres flere ganger, det kalles Refactoring

Lenke til kommentar

Jeg pleier å lage en "hovedklasse", og så lager den de andre klassene. De andre klassene får en referanse til hovedklassen ved behov, slik at de kan kommunisere. F.eks:

 

I "hovedklassen": alarm = new Alarm(this);

Alarm klassen:

 

private readonly MasterClass master;

 

Alarm(MasterClass master) {

    this.master = master;

    ...

}

 

Hvordan koden skal organiseres er noe man finner ut etter hvert, med erfaring. Man trenger ikke tenke på å lage den perfekte koden i første omgang. De fleste prosjekter vil modifiseres flere ganger, det kalles Refactoring

Hei, jeg prøver først og fremst nå å lage en Sensor.cs klasse. Jeg vet ikke helt om jeg må overføre all koden der jeg mottar seriell data fra Arduno i denne klassen? Tenkte da å kalle en metode fra denne klassen i Form.cs klassen i det man trykker på start knappen.

Kan dette funke?

Lenke til kommentar

En klasse bør helst gjøre bare en veldefinert oppgave. Så håndtering av serieport bør være en egen klasse. 

Dekoding av data kan være en annen klasse, som da inneholder data. 

 

Serieport kode bør/må ha en egen Thread for mottak. Eks:

private readonly SerialPort     _com;
private Thread                  _receiveThread;

    public ModemHandler(MPMaster master, int port)
    {
        string sPort = "COM" + port;
        try
        {
            _com = new SerialPort(sPort);
            _com.BaudRate = 9600;
            _com.DataBits = 8;
            _com.Parity = Parity.None;
            _com.StopBits = StopBits.One;
            _com.ReadTimeout = 3000;
            _com.WriteTimeout = 3000;
            _com.Open();
            _isACtive = true;

            _receiveThread = new Thread(Receive);
            _receiveThread.Start();
        }
        catch (Exception ex)
        {
            Console.WriteLine("ModemHandler port " + port + " : failed to open COM port " + ex.Message);                
        }

   }

    private void Receive()
    {
        string data = string.Empty;
        try
        {
            while (true)
            {
                try
                {
                    _timedOut = false;
                    data = _com.ReadLine();
                }
                catch (TimeoutException)		// It will timeout
                {
                    _timedOut = true;
                }
               ... handle data ...
            }
        }
        catch (IOException)
        {
            Thread.CurrentThread.Abort();              // abort the thread
        }
        catch (ObjectDisposedException)
        {
            _receiveThread = null;
        }
    }
Lenke til kommentar

Ok takk, men når jeg mottar seriell data i en klasse, så må jeg overføre det til en annen klasse og splitte opp strengen der. Skulle vel egentlig helst da hatt en eller annen slags array i Sensor.cs klassa hvor jeg lagrer dataene  :hmm:. I tillegg må jeg overføre disse sensordataene til tex bokser i Form.cs klassen . Det er disse overgangene jeg sliter med egentlig.

Endret av Hårek
Fjernet unødig sitering av kode
Lenke til kommentar

Form-klassen kan være "Master", som eier andre klasser. 

Receive Thread vil pushe streng til dekoder. Så vil dekoder pushe data til Form. Der er det en ting du må passe på - Form liker ikke å bli styrt av en annen tråd, det gir IllegalCrossThreadCalls.

Løsning: https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...