Wysyłanie i odbieranie ramek po RS232

2015-01-03 16:23
0

Witam

Mam problem z komunikacją po rs232.
Nie potrafię zmusić programu aby wysyłał i odbierał dane z rs.

Program ma za zadanie wysłać zapytanie do urządzenia, pobrać 1 ramkę, wyświetlić wynik i przejść do następnego zapytania.
Generalnie są 3 zapytania.

Zapytanie 1 - status
Zapytanie 2 - waga
Zapytanie 3 - waga_tymczasowa

Zrobiłem już jakąś transmisję ale zdarza się że dane ze statusu trafiają do wagi, wynik wagi jest zafałszowany.
Wydaje mi się że problem polega na buforze. Mam wrażenie że gdy przechodzę do zapytania 2 to przychodzi ramka ze statusu.

Funkcje potrzebne do RS232

int __fastcall Read_Comm(HANDLE hComm,
                         LPDWORD lpNumberOfBytesRead, DWORD Buf_Size)
{
    DWORD nNumberOfBytesToRead;

    ClearCommError(hComm, &Errors ,&Stat);

    if (Stat.cbInQue > 0)
      {
        if (Stat.cbInQue > Buf_Size)
            nNumberOfBytesToRead = Buf_Size;
          else
            nNumberOfBytesToRead = Stat.cbInQue;

        ReadFile(hComm, &Buffer_I[0], nNumberOfBytesToRead,
                 lpNumberOfBytesRead, NULL);
      }
      else
        *lpNumberOfBytesRead = 0;
    return TRUE;
} 

Zapytanie 1 - Status

 void sprawdzStatus()
    {
        FlushFileBuffers(hComm);
        WriteFile(hComm, status, sizeof status, &RS_ile, 0);
        Read_Comm(hComm, &Number_Bytes_Read, sizeof(Buffer_I));
        Sleep(100);
        if (Buffer_I[0] == 02 && Buffer_I[1] == 03 && Buffer_I[2] == 04 && Buffer_I[3] == 00 && Buffer_I[4] == 00 && Buffer_I[5] == 00 && Buffer_I[6] == 03) {
             status_wagi = true;
        }
        if (Buffer_I[0] == 02 && Buffer_I[1] == 03 && Buffer_I[2] == 04 && Buffer_I[3] == 00 && Buffer_I[4] == 00 && Buffer_I[5] == 00 && Buffer_I[6] == 01) {
             status_wagi = false;
        }
        blokada_pomiaru = false;
    }

Zapytanie 2 - Waga

void licznikGlowny()
{
     FlushFileBuffers(hComm);
     WriteFile(hComm, wagaGlowna, sizeof wagaGlowna, &RS_ile, 0);
     Read_Comm(hComm, &Number_Bytes_Read, sizeof(Buffer_I));
     Sleep(100);
     wynik2=(Buffer_I[4]*65536)+(Buffer_I[5]*256)+Buffer_I[6];
} 

I teraz w Timer co określony czas wywołuję funkcję.

void __fastcall TForm3::Timer1Timer(TObject *Sender)
{
    zmienna++;
    if(zmienna >= 5) zmienna = 0;

    if (zmienna == 2) {
         licznikGlowny();
    }
    if (zmienna == 4) {
         sprawdzStatus();
    }
} 
W jaki sposób masz zadeklarowany ten Buffer_I oraz wagaGlowna? - mychal 2015-01-03 16:31

Pozostało 580 znaków

2015-01-03 16:34
0
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <cmath>

#include "Unit3.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#define cbOutQueue 8          //rozmiar bufora danych wyjściowych
#define cbInQueue  8          //rozmiar bufora danych wejściowych
TForm3 *Form3;
    unsigned char    Buffer_O[cbOutQueue]; // bufor danych wyjściowych
    unsigned char    Buffer_I[cbInQueue]; // bufor danych wejściowych
    DWORD   Number_Bytes_Read; // liczba bajtów do czytania
    char statuss;
    static DCB dcb;
    char hex[6] = {0x02,0x03,0x00,0x02,0x00,0x02};
    char status[6] = {0x02,0x03,0x00,0x04,0x00,0x02};
    char wagaGlowna[6] = {0x02,0x03,0x00,0x02,0x00,0x02};
    char stat[8];
    HANDLE hComm;
    char lpBuffor_read[8], lpBuffor_write[8];
    DWORD RS_ile;
    bool abContinue = true;
    int isRead = false;
    bool CommFlag;
    DWORD   fdwEvtMask;    // informacja o aktualnym stanie transmisji
    COMSTAT Stat;             // dodatkowa informacja o zasobach portu
    DWORD   Errors;           // reprezentuje typ ewentualnego błędu
    int liczba0 = 12.5;
    int mod0, mod1, mod2, mod3, mod4, mod5, mod6, mod7, mod8,wynik1;
    unsigned char mo0, mo1, mo2, mo3, mo4, mo5, mo6, mo7, mo8, wynik;
    unsigned char mmo0, mmo1;
    double wynik2;
    char wynikk[6];
    bool status_wagi, blokada_pomiaru, blokada_pomiaruwagi = false;
    int zmienna;

//---------------------------------------------------------------------------

Pozostało 580 znaków

2015-01-03 17:08
0

ściągnij http://www.serial-port-monitor.com/ zainstaluj i zobacz co jest wysyłane do urządzenia


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

2015-01-03 17:20
0

Monitor RS pokazuje dane tak trzeba.

Jak mogę sprawdzić czy transmisja się zakończyła.

Pozostało 580 znaków

2015-01-03 17:56
1

co to wg Ciebie znaczy transmisja się zakończyła.
Jaki to typ wagi? Z doświadczenia mogę powiedzieć, że część urządzeń wymaga znaku końca linii 0D 0A po każdej komendzie co nie zawsze znajduje się w dokumentacji.


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

2015-01-03 18:53
0

Generalnie waga odpowiada ładnie gdy wywołuję tylko jedno zapytanie.

Chciałbym tak zrobić żeby po wywołaniu funkcji sprawdzStatus() odebrał dane sprawdził czy jeszcze coś idzie jak nie to wywołaj drugą funkcję licznikGlowny(); i tak w koło.

Wtedy nie powinno być sytuacji że na wysłane zapytanie np sprawdzenie statusu przychodzi odpowiedz na zupełnie inne zapytanie.

Pozostało 580 znaków

2015-01-03 19:08
0

to z czym masz w końcu problem bo piszesz, że waga odpowiada


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

2015-01-03 19:49
0

No waga odpowiada, chciałbym żeby odbieranie danych było tylko w określonym czasie.

Wysyłam ramkę o status-> czekam 5 sekund w tym czasie odbieram dane-> zamykam możliwość odbierania danych->Wysyłam ramkę o wagę-> otwieram możliwość odbierania danych-> czekam 5 sekund w tym czasie odbieram dane->zamykam możliwość odbierania danych-> itd

Pozostało 580 znaków

2015-01-03 20:16
0

to tak nie działa - po jednej stronie masz komputer i tutaj masz jakieś pole manewru ale po drugiej stronie masz wagę i na nią nie masz wpływu. Nie możesz założyć, że np. po 5 sekundach to jak Ci waga odpowie to będzie za późno. Waga po prostu Ci coś odeśle i ją to nie interesuje co z tą odpowiedzią zrobisz. Nie wiem jaki masz model wagi (nie napisałeś) ale większość z jakimi miałem do czynienia (min. radwag, fawag, rhewa, axis, digi, mettler toledo) odpowiadają w taki sposób, że wiadomo na jaki rozkaz (albo kod rozkazu jest w ramce odpowiedzi albo są po prostu różne ramki). Inna sprawa, że nie zdarzyło mi się żebym musiał czekać dłużej na odpowiedź od wagi niż kilka - kilkanaście milisekund (oczywiście o ile nie było żadnego błędu po drodze)


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

2015-01-03 20:48
0

Typ wagi to WMTP

No dobrze ale skąd mogę wiedzieć że dane przyszły już całe, w monitorze portu widzę że przyszło ale czy jest jakaś flaga którą mogę badać.

W tej wadze aby odczytać dane które mnie interesują muszę wysłać 3 różne ramki.
W odpowiedzi dostaje ramki, które są bardzo podobne do siebie, np. ramka odpowiedzi o statusie wygląda tak 02 03 04 00 00 00 01 08 F3, ramka odpowiedzi z wagą wygląda tak 02 03 04 00 00 04 23 8A 2A.

Teraz jak je rozróżniać i interpretować.
Czy rozwiązanie poniżej wystarczy na złapanie całej ramki.

        WriteFile(hComm, status, sizeof status, &RS_ile, 0);
        Read_Comm(hComm, &Number_Bytes_Read, sizeof(Buffer_I)); 

Pozostało 580 znaków

2015-01-03 21:14
0

jeśli wiesz, że wszystkie ramki zaczynają się na 02 03 04 i mają 9 bajtów to przede wszystkim tak sprawdzaj czy ramka jest cała. Czy da się je odróżnić tego nie wiem bo nie wiem co oznaczają poszczególne bajty. Co do ostatniego pytania to musisz uważać bo jak podłączałem się przez konwerter usb-rs noname to miał tendencję do zwracania na raz tylko 8 bajtów i po resztę trzeba było ponownie robić ReadFile. Ogólnie dobrze by było zwracać lpNumberOfBytesRead


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0