PropBasic and One-wire

2»

Comments

  • PropBASIC subroutines are not low-level code; what they do is save space by compiling high-level commands like OWWRITE into one location. I haven't used PropBASIC in a long time, but I have used it and know it's possible.

    I'm using a 1-Wire thermometer in my latest product development project, so I freshened up my code. Yes, this is Spin, but Spin is easy to read and the code is documented. You should be able to translate it to PropBASIC with just a little effort. At present, the code expects one device on the line so that it can read the serial number (1W search is a big chunk of code that I haven't adapted to Spin). After it has the serial number it uses that to read back the temperature; this will show you how to use the MATCH ROM command.

    As has been suggested, all of the necessary details are in the device documentation.
    Jon McPhalen
    Hollywood, CA
    It's Jon or JonnyMac -- please do not call me Jonny.
  • jonesjones Posts: 275
    edited 2019-01-29 - 17:41:37
    Discovery wrote: »
    Any ideas?

    Yes. Read the datasheet, especially the section I pointed you to, and compare that to Jon's spin code. It doesn't matter whether or not you write in spin; I don't either, but it isn't that difficult to figure out what his code is doing. Be aware that I haven't used one-wire devices in any of my projects, so this is as new to me as it is to you.

    The datasheet example I pointed you to starts off with sending a reset. Jon's code starts off with ow.reset. That should make sense. PropBasic has OWRESET.
    Next, the devices respond with a "presence" pulse. Apparently Jon doesn't bother to look for that. It just shows there are devices on the bus.
    Next, send a MATCH ROM command. Jon does: ow.write(MATCH_ROM). Again, pretty obvious. MATCH_ROM is $55, as you know. In PropBasic, that's OWWRITE DQpin, $55\8.
    Next, send the 64-bit serial number. Jon suggested you communicate a byte at a time, and he represents the s/n as an array of 8 bytes. His code uses a loop to transmit the array contents, a byte at a time.
    Next, send the convert T command ($44). Nothing hard here, it's just ow.write(CVRT_TEMP). Naturally you need to change that into PropBasic syntax.
    Now, if you had read that "1 Wire Bus System" section I suggested, you'd know that during a temperature conversion, the device will return a 0. When the conversion is done, it returns a 1. Jon uses a loop to continuously read the state of the line and tests to see if it has changed from 0 to 1. When it does, he knows the conversion is complete. The example talks about holding the line high, but that's if the device is powered through the data line which you apparently aren't doing since your working code doesn't have that step. If you power the device with a connection to the Vdd line, it's not necessary. That's all in the datasheet, which I took the time to look over. It's your project, shouldn't you take the time to study it?

    In your previous attempts, instead of testing to see if the conversion was complete, you added PAUSE 750, which just waits long enough. The datasheeet states that the max conversion time is 750 ms, so either way should work. If the conversion completes in less than 750 ms, Jon's way won't waste extra time and will be faster.

    So by now you've told a specific sensor to do a conversion, and it has data you want to read. If you look at the example, you'll see that to get those data, you need to repeat the process of sending the serial number. Jon repeats the ow.reset, ow.write(MATCH_ROM), and the loop to send the 8 bytes of the s/n.

    You can take it from there. If you run into something in the Spin code you don't understand, look in the Propeller Manual, where Spin commands are documented. Use Google to find out how others have done things, and be prepared to experiment. You say your expertise isn't writing low-level code, but this really isn't all that low-level. Bean did the low-level part when he included the one-wire commands in PropBasic. Jon provided working code, which shows the steps to get data from a specific device on a 1-wire bus, and his code is pretty easy to match up to the datasheet example. If this all seems too complex, you need to back up and start with some simpler projects and work your way up to this.

    [edit] Sorry that I wasn't paying attention to see if anyone else had posted, so I was referring to Jon's earlier post.
  • JonnyMacJonnyMac Posts: 6,156
    edited 2019-01-29 - 19:25:05
    Apparently Jon doesn't bother to look for that.
    Not true. My reset() method looks for the presence pulse and provides a 2-bit line status response to the caller. The presence pulse is how my code knows there is something connected to the bus. Here's the PASM code for reset and presence detection.
    ' -----------------                                              
    ' Reset 1-Wire bus                                              
    ' -----------------                                              
    '                                                                
    ' %00 = bus short                                               
    ' %01 = bad response; possible interference on bus              
    ' %10 = good bus & presence detection                           
    ' %11 = no device                                                
                                                                     
    owreset                 mov     value, #%11                     ' assume no device
                            or      dira, owmask                    ' bus low
                            mov     usecs, #500                     ' reset pulse                     
                            call    #delayus                         
                            andn    dira, owmask                    ' release bus
                            mov     usecs, #5                        
                            call    #delayus                         
                            test    owmask, ina             wc      ' sample for short, 1W -> C
                            muxc    value, #%10                     ' C -> value.1
                            mov     usecs, #70                       
                            call    #delayus                         
                            test    owmask, ina             wc      ' sample for presence, 1W -> C
                            muxc    value, #%01                     ' C -> value.0                        
                            mov     usecs, #400                      
                            call    #delayus                         
                            wrlong  value, iopntr                   ' update hub
                            jmp     #cmdexit
    
    Jon McPhalen
    Hollywood, CA
    It's Jon or JonnyMac -- please do not call me Jonny.
  • jonesjones Posts: 275
    edited 2019-01-30 - 01:05:14
    JonnyMac wrote: »
    Apparently Jon doesn't bother to look for that.
    Not true.
    I shoulda known that was a bogus assumption! Thanks for the clarification, and the code.

    [edit] I just checked the PropBasic docs, and OWRESET DQPin{,statusVar} suggests that Bean's reset probably tests the presence pulse too, and returns a value in statusVar.
  • Jon and Bean,
    The following is the actual code that compiles but does not read temperature. It appears to meet all the requirements in the data sheet.

    OWRESET DQPin
    PAUSE 750
    OWWRITE DQPin, $55\8 'MATCH
    OWWRITE DQPin, $D5\8
    OWWRITE DQPin, $00\8
    OWWRITE DQPin, $08\8
    OWWRITE DQPin, $02\8
    OWWRITE DQPin, $93\8
    OWWRITE DQPin, $82\8
    OWWRITE DQPin, $84\8
    OWWRITE DQPin, $10\8
    PAUSE 750
    OWWRITE DQPin, $44\8 'CONVERT
    PAUSE 750
    OWWRITE DQPin, $55\8 'MATCH
    OWWRITE DQPin, $D5\8
    OWWRITE DQPin, $00\8
    OWWRITE DQPin, $08\8
    OWWRITE DQPin, $02\8
    OWWRITE DQPin, $93\8
    OWWRITE DQPin, $82\8
    OWWRITE DQPin, $84\8
    OWWRITE DQPin, $10\8
    PAUSE 750
    OWWRITE DQPin, $BE\8 'READ SCRATCH PAD
    OWRESET DQPin
    PAUSE 750
    OWREAD DQPin, value\16
    \SHL value,#16
    \SAR value,#16

    The ID of the DS18S20 was read by a BS2p and verified as correct.

    I don't see a problem here.

    Discovery

  • JonnyMacJonnyMac Posts: 6,156
    edited 2019-01-30 - 00:38:26
    Okay, I give. Where can I get the latest PropBASIC binary, and which IDE is best suited for it? You're doing things the hard way and I can't endure the pain any longer. :lol:
    Jon McPhalen
    Hollywood, CA
    It's Jon or JonnyMac -- please do not call me Jonny.
  • Discovery, why the reset after the command to read the scratchpad? That's not in the example, and I suspect it will derail the read. Also, you should not need the PAUSE 750 except after you send the convert command. That's to allow time for the temperature conversion, not the one-wire bus.

    Jon, I still use the ancient version of PropBasic with BST. I think PropellerIDE now works with the current version of PropBasic, but I haven't used it.
  • What I find so interesting is the following code works perfectly.

    OWRESET DQPin
    PAUSE 750
    OWWRITE DQPin, $44CC\16 'SKIP & CONVERT
    OWRESET DQPin
    PAUSE 750
    OWWRITE DQPin, $BECC\16 'SKIP & READ SCRATCH PAD
    OWREAD DQPin, value\16 'READ THE TEMPERATURE
    \SHL value,#16
    \SAR value,#16

    No problem at all here.

    Discovery
  • jonesjones Posts: 275
    edited 2019-01-30 - 01:17:05
    Notice that in the code that works, you don't send a reset after the command to read the scratchpad.

    In the code you are trying to get working, you do. Shouldn't that suggest you don't want to send that reset? Don't you think that resetting the device probably cancels the command you just sent?
  • I will remove the OWRESET.

    Discovery
  • The OWRESET DQPin was removed and the code produces the same results...no reading.

    Discovery
  • Okay. I'm guessing you have a byte order problem with the 64-bit serial number. I didn't see the byte order clearly stated in the datasheet, but it does say that $10 is the family code for the device, which is the least significant byte.

    Jon's most recent code appears to read the s/n in the same byte order as it sends it, and if you look at the left side of the flowchart on pg 16 of the datasheet (ROM commands), the $33 Read ROM appears to be LSB first. Your code send MSB first (the $10 family code is last, and I think that's backwards).

    Since I don't have a DS18S20, I can't test my assumptions, but I think that might be the problem. Maybe Jon can shed some light on this.
  • I tried reversing the 64 bit ID earlier but that was with the 32, 24 and 24-bit configuration. I will reverse the code in the byte configuration. Hopefully, that will correct the problem.

    Discovery
  • The code now looks as shown below. The code did not produce a temperature reading.

    OWRESET DQPin
    PAUSE 750
    OWWRITE DQPin, $55\8 'MATCH
    OWWRITE DQPin, $10\8
    OWWRITE DQPin, $84\8
    OWWRITE DQPin, $82\8
    OWWRITE DQPin, $93\8
    OWWRITE DQPin, $02\8
    OWWRITE DQPin, $08\8
    OWWRITE DQPin, $00\8
    OWWRITE DQPin, $D5\8
    PAUSE 750
    OWWRITE DQPin, $44\8 'CONVERT
    PAUSE 750
    OWWRITE DQPin, $55\8 'MATCH
    OWWRITE DQPin, $10\8
    OWWRITE DQPin, $84\8
    OWWRITE DQPin, $82\8
    OWWRITE DQPin, $93\8
    OWWRITE DQPin, $02\8
    OWWRITE DQPin, $08\8
    OWWRITE DQPin, $00\8
    OWWRITE DQPin, $D5\8
    PAUSE 750
    OWWRITE DQPin, $BE\8 'READ SCRATCH PAD
    PAUSE 750
    OWREAD DQPin, value\16
    \SHL value,#16
    \SAR value,#16

    The code compiles fine. My feeling is that there needs to be at least another instruction sent to the DS18S20 to complete the MATCH function. At this point I have no idea.

    Discovery
  • Try this code, replace with your serial number from your ds18b20.
    Made with bst basic.

    Well, basic is very difficult, spin is 10 times easier.
    ' Reads the temperature from a Dallas DS18B20
    ' Converts it to ascii and sends it to the PC
    ' Connect DS18B20 DQ pin to PIN 1 on the propeller
    ' Don't forget the 4.7K pullup resistor too...
    '
    DEVICE P8X32A, XTAL1, PLL16X
    FREQ 80_000_000
    
    ' Define CONs
    Baud     CON "T115200"
    
    ' Define PINs
    DQPin    PIN 1 INPUT   ' 1-Wire communication pin to DS18B20
    TX       PIN 30 HIGH   ' Send data back to PC
    
    ' Define DATA (DATA, WDATA, LDATA)
    Message    DATA "The temperature is "
    TempWhole  DATA "1234."
    TempFrac   DATA "1234 Degrees C", 13, 0
    
    ' Define variables (LONGs only)
    temp     VAR LONG
    value    VAR LONG     ' Temperature
    
    ' Start of main code
    PROGRAM Start
    
    Start:
      ' Main code loop
      DO
        ' Perform a temperature conversion
        OWRESET DQPin
        OWWRITE DQPin, $44CC\16  ' SkipROM($CC) & Convert($44)
        PAUSE 750           ' Wait for conversion
    
        ' Read temperature value
    '    OWRESET DQPin
    '    OWWRITE DQPin, $BECC\16  ' SkipROM($CC) & Read Scratch($BE)
    '    OWREAD DQPin, value\16
    
        ' Read temperature value
        OWRESET DQPin
        OWWRITE DQPin, $55\8  'Match($55)
    
        OWWRITE DQPin, $3A13F128\32 'MATCH 64 bit serial number
        OWWRITE DQPin, $A4000004\32 'Number backwards
    
        OWWRITE DQPin, $BE\8  ' Read Scratch($BE)
        OWREAD DQPin, value\16
    
        ' Sign extend value from 16 bits to 32 bits
        \ SHL value,#16
        \ SAR value,#16
    
        ' Convert value to ascii
        temp = value / 16              ' Get whole value
        tempWhole = STR temp, 4, 7    ' Signed leading spaces, no zero terminator
        temp = value AND 15            ' Get fractional value
        temp = temp *  625             ' 10000 / 16
        tempFrac = STR temp, 4, 4 ' Unsigned leading zeros, no zero terminator
    
        ' Output temperature message to PC
        SEROUT TX, Baud, Message
      LOOP
    END
    
    
    
    Yes Frida is my watchdog!
  • Thank you...I will give it a try.

    Discovery
  • Hi frida,

    I don't understand the following code...

    OWWRITE DQPin, $3A13F128\32 'MATCH 64 bit serial number
    OWWRITE DQPin, $A4000004\32 'Number backwards

    The ID number to match is 10848293020800D5.
    How did you arrive at $3A... and $A4...?

    Sincerely,

    Discovery
  •  28F1133A040000A4 my serial number 
    
      1  2  3  4  5  6  7  8 bytes
     28 F1 13 3A 04 00 00 A4 serial number
    
      8  7  6  5  4  3  2  1 bytes backward
     A4 00 00 04 3A 13 F1 28 serial number backward
    
     first send byte 1 to 4
        OWWRITE DQPin, $3A13F128\32 'MATCH 64 bit serial number
     then  send byte 5 to 8
        OWWRITE DQPin, $A4000004\32 'Number backwards
    
    
    
    
    10848293020800D5 yours serial number
    
     1  2  3  4  5  6  7  8 bytes
    10 84 82 93 02 08 00 D5 serial number
    
     8  7  6  5  4  3  2  1 bytes
    D5 00 08 02 93 82 84 10 serial númber backwards
    
     first send byte 1 to 4
        OWWRITE DQPin, $93828410\32 'MATCH 64 bit serial number
     then  send byte 5 to 8
        OWWRITE DQPin, $D5000802\32 'Number backwards
    
    
    Yes Frida is my watchdog!
  • Thank you Frida.

    Discovery
  • Frida,
    Perfect...that works!

    I would never have guessed that configuration of bytes.

    You seem to be in tune with PropBasic and DS devices. You solved one of my two problems for upgrading my factory control system. The first was reading several temperatures in the process.

    The second problem is reading the four analog voltages from the DS2450 and setting the four digital outputs for a DS2450. The match device is now understood...are there additional tricks for interfacing PropBasic with the DS2450?

    Incidentally, how do I get the TX output from my Propeller Activity Board into the laptop computer for temperature display?

    Discovery
Sign In or Register to comment.