Newsgroup: it.comp.lang.visual-basic
Titolo: Bilancia seriale

Ciao a tutti.
Devo interfacciarmi con una bilancia elettronica, tramite porta seriale
Con un programma in Vb6
In pratica devo leggere le pesate e il prezzo impostato sulla bilancia.
La bilancia non manda i dati automaticamente, ma devo chiederli.
Ossia devo inviare dei comandi e ipoteticamente la bilancia dovrebbe darmi
la risposta.
Il produttore della bilancia mi ha mandato questo schema di comunicazione.
      Comando
Esc                    1BH
?
Spazio
Nnn                    numero prodotto
Cr Lf
      Risposta
?
spazio
ecc.
ecc.
.
.
.
Cr Lf
Come faccio ad inviare questo comando e a ricevere la risposta???
Ho provato ad usare il controllo Mscomm ma non ho ottenuto nulla.
Vi riporto qlche riga di codice
Dim lVar As Long
Private Sub CmdInvio_Click()
    ' Invio il comando alla bilancia
    lVar = &H1B
    MSComm1.Output = lVar & "? 1  " & vbCrLf
End Sub
Private Sub Form_Load()
    MSComm1.CommPort = 1 
    MSComm1.Settings = "9600,O,7,1" ' Le impostazioni della seriale
    MSComm1.RThreshold = 1 
    On Error Resume Next 
    MSComm1.PortOpen = True
    If Err Then 
        MsgBox "Impossibile aprire la COM" & MSComm1.CommPort & vbCrLf &
Error$
    Else
        MsgBox ("Porta aperta correttamente")
    End If
    On Error GoTo 0
End Sub
Private Sub MSComm1_OnComm()
    Dim Rx$
    Rx$ = MSComm1.Input
    If Len(Rx$) Then ' Se ho ricevuto qualcosa lo scrivo nella TextBox
        Text1.Text = Text1.Text & Rx$
    End If
End Sub
Vi prego aiutatemi sono disperato, grazie
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

    MSComm1.Output = lVar & "? 1  " & vbCrLf
Non c'č uno spazio in piů dopo il numero?
MSComm1.Output = lVar & "? 1" & vbCrLf
oppure forse:
MSComm1.Output = lVar & "? 001" & vbCrLf
E poi prova mettendo il buffer di ricezione della seriale = 1 byte.
-- 
E Pluribus UNIX.
News 2002 [v 2.07] / StopDialer / PopDuster - 
http://www.socket2000.com
Akapulce portal: 
http://www.akapulce.net

 E poi prova mettendo il buffer di ricezione della seriale = 1 byte.
Giusto, poi direi di stare attento al fatto che non è detto che la risposta 
arrivi in un colpo solo, anzi, con RThreshold e buffer a 1 è sicuro che non 
arriverà insieme.
Dovrebbe usare una variabile stringa che viene continuamente accodata nella 
OnComm, se contiene un "?" butta via tutto quello che precede il "?", 
continua ad accodare fino al raggiungimento del terminatore (vbCrLf) e a 
quel punto interpretare e svuotare la stringa che fa da buffer.
Ciao 

     MSComm1.Settings = "9600,O,7,1" ' Le impostazioni della seriale
Lavoro con le seriali da anni, ed è la prima volta che vedo la parità 
dispari.
Sei sicuro?
Alberto
-- 
Henry David Thoreau: L'uomo è tanto più ricco quanto meno costano i 
suoi piaceri.

quel punto interpretare e svuotare la stringa che fa da buffer.
Copio e incollo dall'interfaccia vb alla ns.bilancia:
___
Declare Function GetTickCount Lib "kernel32" () As Long
___
Fine = GetTickCount + 2000           '    TEMPO LIMITE RISPOSTA 2 sec
  Do:      DoEvents
   If MsComm1.InBufferCount > 0 Then RxBuff = RxBuff & MsComm1.Input
 
   If InStr(RxBuff, vbLf > 0 Then Exit Do
   If GetTickCount > Fine Then GoTo ErrCOM
  Loop
PS: Ho messo un GoTo, ma  nessuno è perfetto   ;-)
--
ciao
  Stefano

 PS: Ho messo un GoTo, ma  nessuno è perfetto   ;-)
Personalmente non farei un loop di attesa in un evento che è designato 
proprio ad attendere dati e lo fa meglio essendo già di per se asincrono.
Ciao 

 Sei sicuro?
Me lo ha specificato il produttore della bilancia.
Cmq ho provato anche ad impostarlo diversamente, niente da fare.


     MSComm1.Output = lVar & "? 1  " & vbCrLf
Se tu componessi la stringa e la mandassi in Output successivamente, 
con un breakpoint avresti visto subito una cosa strana:
Quel carattere ESC, sei sicuro che sia la stringa "27"?
Secondo me è un singolo char con carattere Ascii 27.
Anzichè
MSComm1.Output = CStr(lVar) & "? 1  " & vbCrLf
prova
MSComm1.Output = Chr$(lVar) & "? 1  " & vbCrLf
Ciao
Alberto
-- 
Konrad Adenauer: All'intelligenza Dio ha posto limiti, alla stupidità 
no.

 ha scritto nel messaggio 

Vero, OnComm è senz'altro più elegante, ma il pc su cui gira il sw non fa altro
che comunicare con bilance, quindi ho lasciato il polling, più semplice da
testare in caso di problemi di comunicazione.
Consiglio all'OP di usare il polling per il test della comunicazione e
successivamente passaare alla funzione OnComm per la versione definitiva,
soprattutto se il programma deve girare insieme ad altri applicativi.
--
ciao
  Stefano

 quel punto interpretare e svuotare la stringa che fa da buffer.
Giusto, provo subito. Grazie


 soprattutto se il programma deve girare insieme ad altri applicativi.
Il loop è infinitamente più pratico. Consiglio però di spezzarlo con 
delle chiamate a Sleep di durata pari ad una frazione del timeout, in 
modo da scaricare la CPU durante il loop stesso.
Lo considero del tutto accettabile, anzi, quasi consigliabile, quando 
la comunicazione seriale (per sua natura asincrona) debba essere invece 
simil-sincrona, come nel caso di questo thread.
Quando invece la comunicazione sia fortemente asincrona (ad esempio se 
il PC è in ascolto e non è il master), occorre assolutamente utilizzare 
l'OnComm.
Ciao
Alberto
-- 
Charles Baudelaire: C'è un solo modo di dimenticare il tempo: 
impiegarlo.

 Alberto
Mi sono perso. :-(
Cosa dovrei fare???


 Cosa dovrei fare???
Innanzitutto, hai sistemato quel CHR$ ?


Cosa dovrei fare???
La discussione verteva sulla possibilità di usare il polling per sentire la
porta, in pratica un Do Loop, come nell'esempio che ti ho postato, e la funzione
OnComm, che in pratica gestisce in modo asincrono la comunicazione.
Sono d'accordo con Albe sul fatto che sia molto più pratico usare il loop per la
gestione della porta, soprattutto in fase di debug del software, tuttavia questo
metodo usa molto la cpu e in determinati casi la cosa può causare problemi se
debbono girare degli altri applicativi.
In questi casi si deve usare la funzione OnComm che viene generata dal programma
in modo asincrono (come un interrupt per intenderci) ogni volta che si verifica
un evento relativo alla comunicazione, e richiede una gestione molto più
complessa.
A te consiglio di usare il loop in polling, almeno per il debug della
comunicazione, poi vedi.
--
ciao
  Stefano

 Innanzitutto, hai sistemato quel CHR$ ?
Si l'ho fatto
MSComm1.Output = Chr$(&H1B) & "? 001" & vbCrLf
ma cmq quando invio la richiesta non succede nulla, nè un errore nè una
risposta della bilancia, assolutamente niente.


risposta della bilancia, assolutamente niente.
Leggo dal tup primo post:
      Comando
Esc                    1BH
?
Spazio
Nnn                    numero prodotto
Cr Lf
quindi direi:
MSComm1.Output = Chr$(&H1B) & "? N01" & vbCrLf 
--
ciao
  Stefano

   Stefano


 Ok provo subito il tuo esempio. grazie
Ho provato ma non funziona.
Perň non ho capito una cosa (scusa ma non sono un genio in vb6)
dove devo inserire queste righe ?
Fine = GetTickCount + 2000 ' TEMPO LIMITE RISPOSTA 2 sec
Do: DoEvents
If MsComm1.InBufferCount > 0 Then RxBuff = RxBuff & MsComm1.Input
If InStr(RxBuff, vbLf > 0 Then Exit Do
If GetTickCount > Fine Then GoTo ErrCOM
Loop
Io le ho messe nella routine che invia il comando alla bilancia subito
dopo l'output
e cosě facendo mi va in ErrCom e non succede niente.
Sto facendo un macello lo so ma non sono molto pratico.
ti prego aiutami.



Prima ancora farei due prove con l'Hyper terminal che c'è tra gli accessori 
di windows.
Una volta che sei riuscito a ottenere una risposta con quello passerei agli 
esperimenti con VB.
Ciao 

 Ciao
Ho provato anche il tuo suggerimento ma il fatto è che non va proprio in
ricezione cioè nonviene richiamata MSComm1_OnComm 
Ma RThreshold lo devo usare o no??
Scusa ma sono un pessimo alunno lo so, ma in 15 anni che programmo non mi
ero mai occupato (fortunatamente) di seriali.


 simil-sincrona, come nel caso di questo thread.
Mmm... potrei essere d'accordo, ma quel DoEvents di SB mi lascia un po' 
perplesso.
Sembra il classico "multithread alla matriciana".
Dato che raramente un programma non ha interazione con l'utente (anche solo 
per visualizzare il peso) ritengo il loop un po' "accrocchioso", se invece 
ha l'unico scopo di leggere il peso e ad es. scrivere i dati su disco è un 
altro discorso.
Ciao 

 disco è un altro discorso.
Ritratto questa parte dato che la comunicazione avviene su richiesta e 
quindi ci si attende una sola risposta solo quando lo decido io.
In questo caso il loop credo sia consigliabile, proprio per il fatto della 
sincronia.
Diverso è il caso di trasmissione in continuo da parte dell'apparecchiatura.
Ciao 

Fabio ha detto questo venerdì :

Innanzitutto, devo confessare di essere un po' condizionato nelle mie 
riflessioni, dal fatto che non uso mai lo stesso applicativo per la 
gestione della seriale e per la parte di interfaccia. Quindi dei tempi 
di loop dell'app che dialoga, e dei potenziali freeze dello schermo, mi 
interesso relativamente.
Il doevents immagino che SB l'abbia messo proprio per far sembrare vivo 
il sistema. In realtà non serve, l'Input del MSComm si popola anche 
senza doevents. Preferisco (come avevo suggerito), mandare in sleep 
l'applicativo periodicamente.
Cioè, se il loop deve durare al massimo, che so, mezzo secondo poi è 
timeout, io ad ogni giro invoco uno sleep di 20ms. Un singolo giro dura 
al massimo 1ms, quindi ho che il sistema è idle e disponibile per la 
quasi totalità del tempo, e la Cpu non ne risente. Ovvio che se il 
telegramma è completato prima del timeout, si esce dal loop.
Ciao
Alberto
-- 
Karl Marx: Le circostanze fanno l'uomo non meno di quanto l'uomo faccia 
le circostanze.

ti prego aiutami.
Lo stiamo facendo, coraggio.
--
ciao
  Stefano

 ricezione cioè nonviene richiamata MSComm1_OnComm
Può essere che la bilancia non riconosca il comando e non ti risponda.
Come dicevo nell'altro post, prova prima di tutto con l'hyper terminal.
Ciao 

altro discorso.
Questione di opinioni, io con il loop vado benissimo.
--
ciao
  Stefano

ero mai occupato (fortunatamente) di seriali.
--
ciao
  Stefano

 Lo stiamo facendo, coraggio.
Vi ringrazio moltissimo, ma è che proprio non mi vuole funzionare
Ti riporto di nuovo il codice che ho modificato con il tuo suggerimento
(credo di aver commesso + di un errore perdonami):
La dich. di GetTickcount l'ho messa in un modulo
e questo è tutto il codice che ho messo nel form.
Dim Fine As Long, RxBuff As String
Private Sub CmdInvio_Click()
    MSComm1.Output = Chr$(&H1B) & "? 001" & vbCrLf
 
    Fine = GetTickCount + 2000 ' TEMPO LIMITE RISPOSTA 2 sec
    Do: DoEvents
    If MSComm1.InBufferCount > 0 Then RxBuff = RxBuff & MSComm1.Input
    If InStr(RxBuff, vbLf) > 0 Then Exit Do
    If GetTickCount > Fine Then GoTo errcom
    Loop
    MsgBox (RxBuff)
errcom:
MsgBox ("errore Com")
End Sub
Private Sub Form_Load()
    MSComm1.CommPort = 1 ' Selezioniamo la COM1
    MSComm1.Settings = "9600,o,7,1" ' Le impostazioni della seriale
    MSComm1.InputLen = 1 'legge un carattere alla volta
    On Error Resume Next 
    MSComm1.PortOpen = True 
    If Err Then 
        MsgBox "Impossibile aprire la COM" & MSComm1.CommPort & vbCrLf &
Error$
    Else
        MsgBox ("Porta aperta correttamente")
    End If
    On Error GoTo 0
End Sub
Appena parte il form mi esce il msg "Porta aperta correttamente"
poi premo sul button cmdinvio e dopo 2 sec. mi esce il msg "Errore com"
ed esce dal ciclo.
che orrori faccio nel codice???
ciao.


ciao.
Metti un:
Errcom:
 MsgBox Rxbuff & " ERROR"
' per vedere se arriva qualcosa.
E proverei anche con un :
 MSComm1.Output = Chr$(&H1B) & "? V01" & vbCrLf
se non va ancora contatta l'assistenza tecnica e fatti specificare meglio i
parametri della porta e della stringa.
--
ciao
  Stefano

 parametri della porta e della stringa.
i parametri li ho modificati in diversi modi ma il risultato è sempre lo
stesso (che poi se metto un parametro che la bilancia non accetta dovrebbe
almeno restituirmi un errore all' apertura della porta???)


almeno restituirmi un errore all' apertura della porta???)
Questo non è affatto detto.
Per esempio il firmware sulla ns bilancia ignora le stringhe in ingresso se non
arrivano correttamente.
Il buffer si inizializza solo dopo aver ricevuto un carattere ESC e il µC passa
alla decodifica solo quando arriva un LF.
Se però superi la lunghezza permessa della stringa si azzera il buffer e resta
di nuovo in attesa di un ESC.
--
ciao
  Stefano

 che orrori faccio nel codice???
Per essere un codice di prova, può andare.
L'errore è in realtà il timeout, quindi è normale, perchè se non ricevi 
risposta entro 2 secondi è giusto che vada in timeout.
Ma, a questo punto, mi chiedo se hai fatto il primo controllo del mondo 
"serial": Il cavo è quello giusto per l'handshaking richiesto?
Alberto
-- 
Léo Campion: Il lavoro è l'occupazione di chi non ha nulla da fare.