Är det en loop som läser av värdet på COMporten?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
carpelux
Inlägg: 1959
Blev medlem: 13 oktober 2007, 12:33:33
Ort: Varnhem

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av carpelux »

Al_Bundy skrev:
Fram och tillbaka, fram och tillbaka...
Googla på Xon & Xoff
Användarvisningsbild
Al_Bundy
Inlägg: 2889
Blev medlem: 11 september 2012, 23:59:50
Ort: The U.S - Chicago
Kontakt:

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av Al_Bundy »

sodjan skrev:> Men kan man verkligen ha handskakning på USB som AVR:en kan kontrollera?

Hårdvaruhandskakning kan vara pyssligt.
Programvaruhandskakning är självklart inget som helst problem,
det är helt oberoende av hur "linjen" ser ut mellan de två parterna
och du har 100% kontroll i din egen kod över det.

> Handskakningen är väll till för att anropa/förvarna att något kommer och motsidan måste vara beredd?

Nej, det skulle jag inte säga. Det är som att ropa till någon och kasta en boll samtidigt
utan att kontrollera att mottagaran är beredd. Det är ingen handskakning. Du måste
vänta tills ("skaka hand" med) mottagaren faktiskt säger att han *är* beredd.
Utveckla vidare. Handskakningen är till för kommunikation för att....?
Användarvisningsbild
Jan Almqvist
Inlägg: 1655
Blev medlem: 1 oktober 2013, 20:48:26
Ort: Orust

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av Jan Almqvist »

Jag tror nog att TS skulle spara mycket jobb på att göra så här:

Välj ett riktigt protokoll.
Låt PC:n vara master som pollar Arduino som är slav.
Provkör varje del för sej mot en beprövad simulator, eller annan enhet som kan vara både master och slav, dvs PC mot simulator och simulator mot Arduino.
Först när detta fungerar provar man PC mot Arduino.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46974
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av TomasL »

Det är väl inga problem att köra data från uC till PC utan protokoll.
Har själv kört i veckor med 115kbit kontinuerlig bit-ström utan handskakning mot Realterm som loggar detta i textfil (filerna blir dock rätt stora :lol: )
Det beror ju naturligtvis vad PC'n gör mer, om det skall fungera, denna gjorde inget annat än just logga.

Så Bundy, funkar det inte så är det du som gör fel (eller dina kompisar på PC-sidan).
Användarvisningsbild
Icecap
Inlägg: 26648
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av Icecap »

Med tanke på Al's generella förklaringar och sätt anser jag fortfarande att Al är källan till det mesta onda.

Men det är i grunden så att båda parter gör fel!
* Al gör fel vid att bara fläska ut data utan att ha koll på om det behövs och utan att ha kommunikation med "de andra".
* "De andra" gör fel vid att inte ha avtalat protokoll osv, dels inbördes och dels med Al och andra "externa".

Att kommunicera och skapa delar av ett projekt fungerar inte(!!!) om det inte finns tydliga och klara riktlinjer först!

Alltså avtalar man (i detta fall) ett protokoll, det kan vara challenge-responce eller hårdvara-handskakning, uppbyggning av värdens representation och i grunden allt som har med kommunikationen att göra. Innan det är klart är det knappast orsak att jobba med programmeringen.

Men med Al's eminenta kommunikationsförmåga - som visat så ofta i detta forum - lär det nog finnas ett protokoll varav Al uppfyller dataformatet men inget annat, helt enkelt för att det var tråkigt att läsa. :wink:
grottan
Inlägg: 478
Blev medlem: 16 maj 2010, 12:16:42

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av grottan »

Förefaller väldigt märkligt att utbildningsledaren inte kan ge eleverna rätt förutsättningar, om jag fattat det hela rätt så är det en Universitetskurs TS går - kan tycka att det på den utbildningsnivån borde vara bättre kvalitet än vad vi ser i denna tråd. Det är ju defacto rena grunder i seriell kommunikation som går snett, handskakning (CTS/RTS eller XON/XOFF) - sånt fick man ju lära sig i gymnasiet på 80-talet och sedan koda rutinerna i assembler.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av sodjan »

> Utveckla vidare. Handskakningen är till för kommunikation för att....?

OK, jag måste försöka skita i denna tråd...
Antingen driver du med alla eller så är du hopplöst obildbar.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av jesse »

Det är väl inte så enormt mycket data som ska in? några hundra tecken per sekund är ju inga problem, och det behövs knappast nån handskakning - kör på bara.

Jag vet att det är knepigt att skriva ett eget PC-program som tar emot data från COM-porten, men jag har faktiskt lyckats. Det är väldigt lite kodexempel (eller svårt att hitta) eller så är exemplen föråldrade (gamla Windows-95 API) eller helt enkelt dåliga...

Man måste kunna polla (= kolla väldigt ofta) ifall det finns data som vill in. Då MÅSTE man snarast läsa in dessa innan bufferten blir full. (Det finns alltid en buffert som operativsystemet tillhandahåller, som fylls på med data)

jag ska kolla om jag hittar någon kod jag har skrivit , så kan du titta... Tror jag försökt i både C, C++, Java och C#. C# var det som var enklast tror jag. Java var ett helvete, som vanligt (COM-porten stöds/stöddes inte i standard-Java, man måste skaffa obskyra bibliotek som inte går att installera)

EDIT: Har du Visual Studio så kan du få en zip-fil med ett C# projekt som läser in strömmande data från en COM-port (som kopplades till en AVR).
Formatet råkar vara NMEA i ASCII(HEX), men kan givetvis vara vad som helst, bara man kan identifiera strängens start och slut. Det är det enda program jag gjort i C# och kunde varit avsevärt bättre, den är delvis ofärdig, men själva kommunikationsbiten fungerar utmärkt!

Här kommer en "förhandsgranskning" på ett par bitar av koden: :P

Kod: Markera allt

// denna metod måste anropas kontinuerligt för att ta emot data från porten.
// rekommenderas mellan 0.25 - 5 sekunders intervall beroende på behov.
public void Check_incoming()
{
	if (connected > 0) connected--;
	string text = port.Read();
	if (text != null && text != "")
	{
		//Console.WriteLine(text);
		// bearbeta inkommande text
		char[] separator = { ':', ',', '*' };
		// sträng-arrayen s innehåller alla argument i NMEA-meningen från 0="$IITXT" till checksumman
		string[] s = text.Split(separator);

		if (s.Length < 6) return; // error
		connected = connection_timeout; // ställ timeout om meddelade kommer in
		int start = 1;
		string kommando = "";
		if (s[0] == "$IITXT")
		{
			adress = toInt(s[1]);
			code = toInt(s[3]);
			checksum = toInt(s[s.Length - 1], 16);
			start = 4;
			kommando = s[start++];
		}
		switch (kommando)
		{
			case "v":
				// läs in VV-parametrar
				for (int i = 0; i < (VV.Length); i++)
				{
					if (i + start > s.Length) break;
					VV[i] = toInt(s[i+start]);
				}
				VV_received = true;
				numberOfCells = VV[20];
				Console.WriteLine("VV received");
				Console.WriteLine("Minibms {0} celler.", numberOfCells);
				if (numberOfCells > MAXANTALCELLER) numberOfCells = MAXANTALCELLER;
				if (numberOfCells < 0) numberOfCells = 0;
				// skapa en cell-lista - behövs ej
				break;
			case "r":
				// läs in celldata - millivolt
				Vmedel = 0;
				Vmax = 0;
				Vmin = 10;
				for (int i = 0; i < (numberOfCells); i++)
				{
					if (i + start > s.Length) break;
					float v = toInt(s[i + start]) / 1000F;
					celler[i].volt = v;
					Console.Write("{0:0.000}  ", v);
					Vmedel += v;
					if (v > Vmax) Vmax = v;
					if (v < Vmin) Vmin = v;
				}
				totalVolt = (float)Math.Round(Vmedel, 1);
				if (numberOfCells != 0)
					Vmedel = Vmedel / numberOfCells;
				Console.WriteLine("");
				for (int i = 0; i < numberOfCells; i++)
				{
					celler[i].avvikelse = (celler[i].volt - Vmedel);
				}
				cellsUpdated = true;
				break;

			case "ta" :
				// läs in temperaturer

				break;
		}


	}
}

Kod: Markera allt

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;

namespace seriell
{
    class Sercomm
    {
        // klassvariabler = Fält

        const int MAXBUFLEN = 1024; // antal inlästa tecken
        byte[] inbuf = new byte[MAXBUFLEN];
        int bufpos = 0;

        public SerialPort port = new SerialPort();
        public string[] ports = SerialPort.GetPortNames();

        // konstruktor - letar upp alla lediga portar och skriver ut en lista
        public Sercomm ()
        {
            // Skriv ut en lista med portar
            Console.WriteLine("Existerande portar:");
            foreach(string pname in ports)
            {
                port.PortName = pname;
                try
                {
                    port.RtsEnable = false;
                    port.Open();
                    Console.WriteLine("Port {0} är ledig.", port.PortName);
                    //Console.WriteLine((port.CDHolding) ? "DCD on" : "DCD off");
                    //Console.WriteLine((port.CtsHolding) ? "CTS on" : "CTS off");
                    port.Close();
                }
                catch (System.IO.IOException)
                {
                    // inget
                }
                catch (System.UnauthorizedAccessException)
                {
                    Console.WriteLine("Port {0} är upptagen.", port.PortName);
                }
            }
        }

        public void Open(string portnamn, int baudrate)
        {
            port.PortName = portnamn;
            port.BaudRate = baudrate;
            port.ReadTimeout = SerialPort.InfiniteTimeout;
            port.Open();
            port.RtsEnable = true;
            Console.WriteLine("Port {0} öppnad, {1} BAUD.", port.PortName, port.BaudRate);
            Console.Beep(440, 200);
        }

        public string Read ()
        {
            int nrOfBytes = port.BytesToRead;
            for (int i = 0; i < nrOfBytes; i++ )
            {
                byte tkn = (byte)port.ReadChar();
                if (tkn != 0x0a)
                {
                    inbuf[bufpos++] = tkn;
                    if (bufpos >= MAXBUFLEN)
                    {
                        bufpos = 0;
                        return "";
                    }
                    if (tkn == 0x0d)
                    {
                        string textrad = "";
                        for (int j = 0; j < bufpos; j++)
                        {
                            char z = (char) inbuf[j];
                            textrad += z;
                           }
                        bufpos = 0;
                        return textrad;
                    }
                    //Console.Write(tkn);
                }
            }
            return null;
        }

        public void Write (string text)
        {
            port.Write(text);
        }

        public void Close ()
        {
            // stäng porten
            if (port.IsOpen)
            {
                port.Close();
                Console.WriteLine("Port {0} stängd.", port.PortName);
                Console.Beep(220, 200);
            }
        }

        public void printBuff ()
        {
            for (int i = 0; i < bufpos; i++)
            {
                byte z = inbuf[i];
                if (z > 31)
                    Console.Write((char)z);
                
                    //Console.Write("[{0:X}]", z);
                    //Console.Write(BitConverter.ToString(inbuf).Replace("-00",""));
            }
            Console.WriteLine("");
        }

    }
}
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av jesse »

En extremt enkel variant i C som läser från COM-port: Problemet här är att fgetc()-funktionen antagligen låser programmet tills ett tecken kommit in. Inte kul. Det ska finnas sätt att komma runt detta (tror det finns en funktion som talar om ifall det finns tecken att läsa. Då måste man anropa den först och använda fgetc() enbart när det verkligen finns data att hämta.

Dom som gör PC-programmet måste väl vara medvetna om hur detta fungerar och hur de ska ta emot data? Detta måste ju fungera innan man kan börja med att kommunicera. Det ska inte finnas frågetecken om hur mycket data som går att ta emot, etc... De ska specificera det och sen ser du till att din AVR skickar den data dom vill ha.

Kod: Markera allt

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <termios.h>

#define PATH "C:\\Documents and Settings\\Admin\\Mina dokument\\Avancerat\\ekg\\"
#define COMPORT "COM1"
#define UTFIL "bms_logg.txt"

FILE *s, *s1, *utfil;
char input[256];

int main() {
    char ch;
    printf("testar att kommunicera med serieporten\n");
    printf("sizeof char = %i\n", sizeof(char));
    printf("sizeof int = %i\n", sizeof(int));
    printf("sizeof short int = %i\n", sizeof(short int));
    printf("sizeof double = %i\n", sizeof(double));

    if ((s = fopen(COMPORT, "r+b")) == NULL) {
        printf ("Port OPEN error: ");
        printf( COMPORT );
        return 0;
    }

    printf("\n----- " COMPORT " open ------\n");
    system( "mode com1: baud=38400 parity=n data=8 stop=1" ) ;

    while (1) {
        ch = fgetc(s); // ( input, sizeof( input ), s) ;
        printf( "%c", ch ) ;
        if (ch == '0') {
            fprintf(s,"\n\r");
        }
    }
    
    fclose(s);
    printf("\nklart!");
    return 0;
}
Användarvisningsbild
swesysmgr
Inlägg: 14950
Blev medlem: 28 mars 2009, 06:56:43
Ort: Göteborg

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av swesysmgr »

sodjan skrev:> Utveckla vidare. Handskakningen är till för kommunikation för att....?

OK, jag måste försöka skita i denna tråd...
Antingen driver du med alla eller så är du hopplöst obildbar.
Bundy är representativ för den moderna ingenjörsarbetskraft Svenska storföretag har att tillgå, är det så konstigt att allt mer av utveckling och produktion hamnar utomlands istället? Läsa på och tänka själv är för jobbigt, bättre att gissa, chansa, plagiera och sitta i möten och allmänblaja istället :)
Nerre
Inlägg: 27229
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av Nerre »

Ja, istället för att ta reda på själv så frågar man nån som man tror vet, och sen när inget funkar så kan man klaga på den som gav rådet istället för att få stå för det själv.

Det är väl det som kallas outsourcing? :)
svanted
Inlägg: 5280
Blev medlem: 30 augusti 2010, 21:20:38
Ort: Umeå

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av svanted »

sällsynt puckade kommentarer ni kommer med...
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av johano »

Nerre skrev:Ja, istället för att ta reda på själv så frågar man nån som man tror vet...
Bör väl snarare vara:
"Ja, istället för att ta reda på själv så frågar man nån som tror sig veta"

/johan
Nerre
Inlägg: 27229
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av Nerre »

Nja, jag upplever tyvärr många gånger att när man ifrågasätter något som en kund hittat på så svarar de "vi frågade xxxxx och fick svaret att vi skulle göra si och så".
ronnylov
Inlägg: 987
Blev medlem: 23 februari 2012, 12:06:19
Ort: Borås

Re: Är det en loop som läser av värdet på COMporten?

Inlägg av ronnylov »

Jag har gjort några program på jobbet som läser av mätinstrument på serieporten. Principen har oftast då varit att om instrumentet får en viss textsträng via serieporten från datorn som motsvarar kommandot "skicka mätvärde" så svarar instrumentet med mätvärdet som en textsträng enligt specifikation i instrumentets manual. Principen jag då använt har varit att först tömma läsbufferten på datorns serieport, skicka kommandot och sedan vänta en liten stund tillräckligt länge för att låta serieporten fylla sin läsbuffert med efterfrågad data och slutligen läsa av serieportens läsbuffert och scanna efter resultat i mottagen data. Detta sker i en loop (alltså töm buffert, skicka kommandot och lyssna) ett antal gånger tills giltigt värde mottagits.

Sedan hur inställningar för handskakning ska vara har jag fått läsa i instrumentets manual. Man får initiera datorns serieport på motsvarande sätt innan man börjar använda den. Nu har jag bara använt LabVIEW för detta och de inbyggda funktionerna där men det har fungerat så då har jag kört vidare på det. Kanske inte bästa eller snabbaste sättet men det funkar och då får det duga. Ofta har det ju varit ganska lite data i taget man behövt läsa så det har inte alltid varit noga med handskakningen.

Principen att instrumentet skickar data hela tiden har jag nog också använt någon gång. Vi har någon våg man kan ställa in att spotta ur sig aktuell uppmätt vikt varje sekund. Men principen då är densamma bara att man slipper skicka kommandot att den ska skicka data utan man läser in data från serieporten tillräckligt länge för att få minst ett mätvärde och konverterar texten till ett tal som motsvarar uppmätt värde (detta funkar eftersom den skickar nyradstecken efter varje mätvärde så det är bara att läsa innehållet mellan två nyradstecken). Denna procedur kör man varje gång man vill ha ett mätvärde och så struntar man i att den skickar data även när man inte behöver den. Genom att tömma läsbufferten inför varje läsning så får man nya färska värden.

Min princip funkar väl inte om man alltid måste ta emot allt som instrumentet skickar utan nöjer sig med att läsa värdet och upprepa inläsningen om det misslyckas.

Så hade jag gjort något program i Arduino eller någon annan MCU-lösning skulle jag troligen lägga in korta textkommandon som den lyssnar efter och svarar på utifrån någon given specifikation som sedan programmeraren för datorprogrammet kan anpassa sig efter. Där behövs det ingen loop som ständigt pollar utan man kanske hellre generar avbrottssignal (interrupt) när data tas emot. Är inte jättehaj på hur man gör där men det känns som det kanske går åt onödig prestanda om den ständigt ska ligga och polla kommunikationen.
Skriv svar