Shop OBEX P1 Docs P2 Docs Learn Events
sending multiple values from stamp to visual basic — Parallax Forums

sending multiple values from stamp to visual basic

robban35robban35 Posts: 32
edited 2012-08-15 09:04 in BASIC Stamp
hi!

i want to send 2 temperatures from my BS2 to a my program in visual basic...
so far one value is working perfect using the serout command in pbasic and in visual basic i used mscomm...from rentron.com
how should the code look like?

regards
Robert

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2010-09-13 08:41
    Please list your code (as an attachment).

    Typically, to send one value from a Stamp to a PC, you'd use a SEROUT statement with one value followed by some kind of delimiter like a space or a comma or a carriage return. To send two values, you'd do the same thing, either using two SEROUT statements or a single SEROUT statement with two values like

    SEROUT ...,[DEC value1," ",DEC value2,CR]
  • robban35robban35 Posts: 32
    edited 2010-09-13 09:09
    if i use serout,,,,[dec value1 , dec value2] like you said...
    how do i get it into visual basic
    i use a program this program....see link.

    http://www.rentron.com/receiving_data.htm

    in this program it says that i should use highbyte and lowbyte....

    is there an easier way or what should i add to my program..

    the bs2 program look the same as in the rentron program although i use the temperature instead.




    dont know how to attach but here´s the program


    ' {$STAMP BS2}
    ' ===================== Define Pins and Variables ================
    DQ CON 2 ' Pin 2 <=> DQ.
    CLK CON 1 ' Pin 1 => CLK.
    RST CON 0 ' Pin 0 => RST (high = active).
    DSdata VAR Word ' Word variable to hold 9-bit data.
    Sign VAR DSdata.BIT8 ' Sign bit of raw temperature data.
    T_sign VAR Bit ' Saved sign bit for converted temperature.
    ' ===================== Define DS1620 Constants ===================
    ' >>> Constants for configuring the DS1620
    Rconfig CON $AC ' Protocol for 'Read Configuration.'
    Wconfig CON $0C ' Protocol for 'Write Configuration.'
    CPU CON %10 ' Config bit: serial thermometer mode.
    NoCPU CON %00 ' Config bit: standalone thermostat mode.
    OneShot CON %01 ' Config bit: one conversion per start request.
    Cont CON %00 ' Config bit: continuous conversions after start.
    ' >>> Constants for serial thermometer applications.
    StartC CON $EE ' Protocol for 'Start Conversion.'
    StopC CON $22 ' Protocol for 'Stop Conversion.'
    Rtemp CON $AA ' Protocol for 'Read Temperature.'
    ' >>> Constants for programming thermostat functions.
    RhiT CON $A1 ' Protocol for 'Read High-Temperature Setting.'
    WhiT CON $01 ' Protocol for 'Write High-Temperature Setting.'
    RloT CON $A2 ' Protocol for 'Read Low-Temperature Setting.'
    WloT CON $02 ' Protocol for 'Write Low-Temperature Setting.'

    Kal CON 11550 ' Constant to be determined.
    rct VAR Word ' A word variable.
    TK VAR Word ' Kelvin temperature.
    TC VAR Word ' Degrees Celsius.
    result VAR Word

    ' ===================== Begin Program ============================
    LOW RST ' Deactivate '1620 for now.
    HIGH CLK ' Put clock in starting state.
    PAUSE 100 ' Let things settle down a moment.
    HIGH RST ' Activate the '1620 and set it for continuous..
    SHIFTOUT DQ,CLK,LSBFIRST,[Wconfig,CPU+Cont] ' ..temp conversions.
    LOW RST ' Done--deactivate.
    PAUSE 50 ' Wait for the EEPROM to self-program.
    HIGH RST ' Now activate it again and send the..
    SHIFTOUT DQ,CLK,LSBFIRST,[StartC] ' Send start-conversion protocol.
    LOW RST ' Done--deactivate.
    ' The loop below continuously reads the latest temperature from
    ' the DS1620.
    again:
    PAUSE 1000 ' Wait a second between readings.
    HIGH RST ' Activate the '1620.
    SHIFTOUT DQ,CLK,LSBFIRST,[Rtemp] ' Request to read temperature.
    SHIFTIN DQ,CLK,LSBPRE,[DSdata\9] ' Get the temperature reading.
    LOW RST
    T_sign = Sign ' Save the sign bit of the reading.
    DSdata = DSdata/2 ' Scale reading to whole degrees C.
    IF T_sign = 0 THEN no_neg1
    DSdata = DSdata | $FF00 ' Extend sign bits for negative temps.
    no_neg1:
    result=dsdata
    DSdata = (DSdata */ $01CC) ' Multiply by 1.8.
    IF T_sign = 0 THEN no_neg2 ' If negative, extend sign bits.
    DSdata = DSdata | $FF00
    no_neg2:
    DSdata = DSdata + 32 ' Complete the conversion.

    '***** check ad592 sensor*****

    LOW 15 ' Discharge the capacitor.
    RCTIME 15, 0, rct ' Time for the volts to rise to 1.3 V.
    TK = Kal/rct*10 + (Kal//rct*10/rct) ' Calculate Kelvin
    TC = TK - 273 ' and Celsius.
    PAUSE 50 ' Slows down the program.



    SEROUT 16,16780,[result.HIGHBYTE,result.LOWBYTE]



    GOTO again ' Repeat forever.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-09-13 09:35
    The program you've shown (on the Stamp side) sends two bytes for the two bytes that make up a 16-bit number like this

    Serout 16,16780,[Result.HighByte, Result.LowByte]

    In order to send two values, you'd just repeat the SEROUT statement with your other variable instead of "Result". That sends a total of 4 bytes, 2 for each value.

    On the PC side, you'd need to modify this code to allow for 4 bytes
    sData = MSComm1.Input ' Get data (2 bytes)
        lHighByte = Asc(Mid$(sData, 1, 1)) ' get 1st byte
        lLowByte = Asc(Mid$(sData, 2, 1))  ' Get 2nd byte
        
        ' Combine bytes into a word
        lWord = (lHighByte * &H100) Or lLowByte
    
    Typically by following that with
    lHighByte = Asc(Mid$(sData, 3, 1)) ' get 3rd byte
        lLowByte = Asc(Mid$(sData, 4, 1))  ' Get 4th byte
        
        ' Combine bytes into a word
        lWord2 = (lHighByte * &H100) Or lLowByte
    
    Remember that this is a fairly "primitive" way for two programs to communicate. There's no error checking. There's no synchronization mechanism. The PC program has to get 4 bytes when it expects it. You might have a look at StampPlot Pro for more complex communication between a Stamp and a PC.
  • robban35robban35 Posts: 32
    edited 2010-09-13 10:39
    i got it working!

    thanks alot!
  • robban35robban35 Posts: 32
    edited 2010-09-14 01:53
    ok, now i have the temperature sensors to work perfect...
    and now i want to control a fan using sering on the basic stamp side and visual basic on the computer side...
    i have a faceplate in VB where i have the temperatures and if the temperature goes to high i want to be able to push a command button and start the fan.

    i have tried serin,,,[pinstate]

    so if the pinstate are 1 then the fan starts
    and if it is 0 the fan stops.

    question is...everytime the stamp goes to serin the program stops and wait´s for a command from VB, how do i get it to continue read the temperatures and at the same time check if the command is sent without paus.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-09-14 08:33
    You can't. The Stamps can only do one thing at a time. When you ask it to receive something using a SERIN statement, it dutifully waits to receive the information. You can put a timeout on the SERIN statement and the Stamp will abandon the attempt after that time, but then it won't pay attention to information sent from the PC (and there is no "hidden" buffer).

    The only solution is to attach some kind of external serial receiver to the Stamp that provides buffering and otherwise runs all the time. Options include this from ProteanLogic and this from Microchip.

    One other possible solution is for the Stamp to poll the PC for the state of your on/off request. In other words, when the Stamp sends a set of two values to the PC, the PC always sends a byte back to the Stamp whose value is 0 or 1. After the two SEROUT statements, the Stamp always does a SERIN which doesn't have to wait because there will always be a byte sent from the PC. The Stamp can compare the value received with the current state of the fan and act accordingly.
  • robban35robban35 Posts: 32
    edited 2010-09-14 10:02
    ok...i tried using the timeout and the fan starts but if i start it and then want to stop it i get a errormessege in my vb program and then exits.

    here´s my bs program

    ' {$STAMP BS2}
    ' ===================== Define Pins and Variables ================
    DQ CON 2 ' Pin 2 <=> DQ.
    CLK CON 1 ' Pin 1 => CLK.
    RST CON 0 ' Pin 0 => RST (high = active).
    DSdata VAR Word ' Word variable to hold 9-bit data.
    Sign VAR DSdata.BIT8 ' Sign bit of raw temperature data.
    T_sign VAR Bit ' Saved sign bit for converted temperature.
    ' ===================== Define DS1620 Constants ===================
    ' >>> Constants for configuring the DS1620
    Rconfig CON $AC ' Protocol for 'Read Configuration.'
    Wconfig CON $0C ' Protocol for 'Write Configuration.'
    CPU CON %10 ' Config bit: serial thermometer mode.
    NoCPU CON %00 ' Config bit: standalone thermostat mode.
    OneShot CON %01 ' Config bit: one conversion per start request.
    Cont CON %00 ' Config bit: continuous conversions after start.
    ' >>> Constants for serial thermometer applications.
    StartC CON $EE ' Protocol for 'Start Conversion.'
    StopC CON $22 ' Protocol for 'Stop Conversion.'
    Rtemp CON $AA ' Protocol for 'Read Temperature.'
    ' >>> Constants for programming thermostat functions.
    RhiT CON $A1 ' Protocol for 'Read High-Temperature Setting.'
    WhiT CON $01 ' Protocol for 'Write High-Temperature Setting.'
    RloT CON $A2 ' Protocol for 'Read Low-Temperature Setting.'
    WloT CON $02 ' Protocol for 'Write Low-Temperature Setting.'

    Kal CON 11225 ' Constant to be determined.
    rct VAR Word ' A word variable.
    TK VAR Word ' Kelvin temperature.
    TC VAR Word ' Degrees Celsius.
    result VAR Word
    pinstate VAR Byte


    ' ===================== Begin Program ============================
    LOW RST ' Deactivate '1620 for now.
    HIGH CLK ' Put clock in starting state.
    PAUSE 100 ' Let things settle down a moment.
    HIGH RST ' Activate the '1620 and set it for continuous..
    SHIFTOUT DQ,CLK,LSBFIRST,[Wconfig,CPU+Cont] ' ..temp conversions.
    LOW RST ' Done--deactivate.
    PAUSE 50 ' Wait for the EEPROM to self-program.
    HIGH RST ' Now activate it again and send the..
    SHIFTOUT DQ,CLK,LSBFIRST,[StartC] ' Send start-conversion protocol.
    LOW RST ' Done--deactivate.
    ' The loop below continuously reads the latest temperature from
    ' the DS1620.
    Main:
    HIGH RST ' Activate the '1620.
    SHIFTOUT DQ,CLK,LSBFIRST,[Rtemp] ' Request to read temperature.
    SHIFTIN DQ,CLK,LSBPRE,[DSdata\9] ' Get the temperature reading.
    LOW RST
    T_sign = Sign ' Save the sign bit of the reading.
    DSdata = DSdata/2 ' Scale reading to whole degrees C.
    IF T_sign = 0 THEN no_neg1
    DSdata = DSdata | $FF00 ' Extend sign bits for negative temps.
    no_neg1:
    result=dsdata
    DSdata = (DSdata */ $01CC) ' Multiply by 1.8.
    IF T_sign = 0 THEN no_neg2 ' If negative, extend sign bits.
    DSdata = DSdata | $FF00
    no_neg2:
    DSdata = DSdata + 32 ' Complete the conversion.

    '***** check ad592 sensor*****
    LOW 15 ' Discharge the capacitor.
    RCTIME 15, 0, rct ' Time for the volts to rise to 1.3 V.
    TK = Kal/rct*10 + (Kal//rct*10/rct) ' Calculate Kelvin
    TC = TK - 273 ' and Celsius.
    PAUSE 50 ' Slows down the program.


    ' send it to VB

    SEROUT 16,16780,[result.HIGHBYTE,result.LOWBYTE]
    SEROUT 16,16780,[tc.HIGHBYTE,tc.LOWBYTE]

    ' check on or off from VB
    SERIN 16,16780,2000,main,[pinstate]
    IF pinstate=1 THEN gohigh
    IF pinstate=0 THEN golow
    GOTO main ' Repeat forever.

    gohigh:
    HIGH 12
    GOTO main

    golow:
    LOW 12
    GOTO main
  • robban35robban35 Posts: 32
    edited 2012-08-13 09:00
    can anyone tell me why the data i send from the bs2 via a max232 using serout 15,84,[result.highbyte,result.lowbyte] ......result 2........result3.... dont come att the right place in my Visual basic program.

    i have about 10 sensors wired to the bs2 and 10 labels in Visual basic

    but when i transfer the data the value from sensor 1 shows in label 3,then sensor 2 at label 4 or sometimes sensor 3 at label 1.
    i want them the show sensor 1 at label 1,2 at label 2 ,3 at label 4


    a piece of my vb program

    ' If comEvReceive Event then get data and display
    If MSComm1.CommEvent = comEvReceive Then

    sData = MSComm1.Input ' Get data (2 bytes)


    lHighByte = Asc(Mid$(sData, 1, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 2, 1)) ' Get 2nd byte
    label1 = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 3, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 4, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    label2 = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 5, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 6, 1)) ' Get 2nd byte
    'Combine bytes into a word
    label3 = (lHighByte * &H100) Or lLowByte


    label1.caption=label1
    label2.caption=label2
    label3.caption=label3
    ..
    ..
    ..




    robban
  • Mike GMike G Posts: 2,702
    edited 2012-08-13 09:59
    robban35, the VB program assumes all sensor bytes are available in the serial buffer, in order from 0..n, on MSComm1.CommEvent = comEvReceive . The fact is, the serial buffer might have a portion of the data stream. For example, bytes 0,1,2,3 arrive on comEvReceive, then 4, 5, 6, 7, 8, 9 arrive on the next event.

    You'll need to check the serial port buffer and make sure it contains all the bytes required to populate the VB form. A good way to align the serial buffer and VB form logic is to send a start byte, number of bytes to expect, followed by the data 10 bytes, and ending with a checksum.
  • robban35robban35 Posts: 32
    edited 2012-08-13 10:14
    do you mean:

    serout 15,84,[result.highbyte,result.lowbyte,0]

    and then in VB
    if sdata=0 then next value?

    could you give me an example?
  • Mike GMike G Posts: 2,702
    edited 2012-08-13 12:09
    I no longer have a copy of VB 6.0. I can provide an example in .NET. The concept is the same though.

    Example packet:

    Start length [ data ] checksum

    ! 10 [1,2,3,4,5,6,7,8,9] 1
    0x21 0x10 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x01
    

    The idea is to frame the incoming byte stream. Then extract the data for use in the Win Form.
  • robban35robban35 Posts: 32
    edited 2012-08-13 12:44
    Mike, do you mean something like this?


    serout 15,84,["!",result.highbyte,result.lowbyte,0]
  • Mike GMike G Posts: 2,702
    edited 2012-08-13 13:04
    No something like this... I placed a 1 second pause in the FOR...NEXT loop to simulate data latency.
    ' {$STAMP BS2p}
    ' {$PBASIC 2.5}
    
    ' Set baud for all STAMP versions
    #SELECT $STAMP
      #CASE BS2SX, BS2P
        N2400        CON     1021 + $8000
        N9600        CON     240  + $8000
      #CASE BS2PX
        N2400        CON     1646 + $8000
        N9600        CON     396  + $8000
      #CASE #ELSE
        N2400        CON     396  + $8000
        N9600        CON     84   + $8000
    #ENDSELECT
    
    START_BYTE       CON     $21  '!
    Tx               CON     16
    DELAY            CON     1000
    BYTES_TO_SEND    CON     10
    LOOPS            CON     5
    
    result           VAR     Word
    checksum         VAR     Byte
    counter          VAR     Byte
    aByte            VAR     Byte
    
    
    Main:
    
      result = 0
      checksum = 0
      counter = 0
    
      aByte = START_BYTE
      GOSUB SendByte
    
      aByte = BYTES_TO_SEND
      GOSUB SendByte
    
      FOR counter = 0 TO LOOPS - 1
        Result = ($30 + counter)*256 + ($41 + counter)
        GOSUB SendWord
    
        PAUSE DELAY
      NEXT
    
      aByte = checksum
      GOSUB SendByte
      'DEBUG CR
    
    GOTO Main
    
    
    SendByte:
      SEROUT Tx, N9600, [aByte]
      'DEBUG HEX aByte, " "
      RETURN
    
    SendWord:
      SEROUT Tx, N9600, [Result.HIGHBYTE, Result.LOWBYTE]
      'DEBUG HEX Result.HIGHBYTE, " ", HEX Result.LOWBYTE, " "
      Checksum = Checksum ^ Result.HIGHBYTE
      Checksum = Checksum ^ Result.LOWBYTE
      RETURN
    

    You could do
    serout 15,84,["!",result.highbyte,result.lowbyte,0] 
    
    if the "0" is the index of the value - result . On the VB side, the program will know here to place the value of result.
  • robban35robban35 Posts: 32
    edited 2012-08-14 08:23
    ok,tried it in the debug windows but didn´t work with my vb program

    this is a peice of my vb program

    Private Sub Form_Load()
    Dim Pins As Long
    ' Fire Rx Event Every Two Bytes
    MSComm1.RThreshold = 28

    ' When Inputting Data, Input 2 Bytes at a time
    MSComm1.InputLen = 28

    ' Use COM1
    MSComm1.CommPort = 1

    ' 2400 baud, no parity, 8 data bits, 1 stop bit
    MSComm1.Settings = "9600,N,8,1"

    ' Make sure DTR line is low to prevent Stamp reset
    MSComm1.DTREnable = False

    ' Open the port
    MSComm1.PortOpen = True




    If MSComm1.CommEvent = comEvReceive Then

    sData = MSComm1.Input ' Get data (2 bytes)

    lHighByte = Asc(Mid$(sData, 1, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 2, 1)) ' Get 2nd byte
    utetemp = (lHighByte * &H100) Or lLowByte


    lHighByte = Asc(Mid$(sData, 3, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 4, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    innetemp = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 5, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 6, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    jordtemp = (lHighByte * &H100) Or lLowByte


    lHighByte = Asc(Mid$(sData, 7, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 8, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    kond1 = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 9, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 10, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    kond2 = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 11, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 12, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    kond3 = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 13, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 14, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    kond4 = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 15, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 16, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    kond5 = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 17, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 18, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    fukt = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 19, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 20, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    ljus = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 21, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 22, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    niva = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 23, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 24, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    larm = (lHighByte * &H100) Or lLowByte


    lHighByte = Asc(Mid$(sData, 25, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 26, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    status = (lHighByte * &H100) Or lLowByte

    lHighByte = Asc(Mid$(sData, 27, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 28, 1)) ' Get 2nd byte
    ' Combine bytes into a word
    auto = (lHighByte * &H100) Or lLowByte




    Label1.Caption = CStr(utetemp)
    Label2.Caption = CStr(innetemp)
    Label3.Caption = CStr(jordtemp)
    Label4.Caption = CStr(kond1)
    Label5.Caption = CStr(kond2)
    Label6.Caption = CStr(kond3)
    Label7.Caption = CStr(kond4)
    Label8.Caption = CStr(kond5)
    Label9.Caption = CStr(fukt)
    Label10.Caption = CStr(ljus)
    Label11.Caption = CStr(niva)
    Label23.Caption = CStr(auto)


    i think i understand your program,mike but i cant figure out how to get it in my vb program

    where is the fault


    the bs2 program is attached
  • Mike GMike G Posts: 2,702
    edited 2012-08-14 09:03
    The problem is related to asynchronous serial communication and Windows events. Windows has no idea how many bytes the stamp intends to send. The COM receive event fires at some point in time. The VB 6 code assumes the serial buffer contains every byte required to populate 10 labels. That's simply not realistic in asynchronous serial communication.

    The VB application must parse the serial buffer and handle any missing or extra data.
  • robban35robban35 Posts: 32
    edited 2012-08-14 09:24
    so what do i have to do / change?
  • Mike GMike G Posts: 2,702
    edited 2012-08-14 10:12
    You need to come up with a protocol - a language - to relay information from the Stamp to the PC. Then write your code, VB 6 and PBASIC, to enforce the protocol.

    Secondly, consider researching asynchronous serial communication in Windows. I believe this is where you are having difficulty. If I get some time, I'll try to roll up the concept in .NET - C#.
    so what do i have to do / change? 
    
    You must update the VB 6 and possibly PBASIC code. In posts 10, 12, 14 and 16 I tried to explain the problem. Do you understand the problem?
  • robban35robban35 Posts: 32
    edited 2012-08-15 09:04
    i got it working, i had mixed up the signals and baudrates....

    thanks!'
Sign In or Register to comment.