TG9541 / W1209

W1209 data logging thermostat with an STM8 eForth interactive console
https://github.com/TG9541/W1209/wiki
MIT License
31 stars 12 forks source link

Need binary .ihx file for W1209 with modified .fs source files #22

Closed paulcrawford closed 4 years ago

paulcrawford commented 5 years ago

Hello Thomas,

As suggested I am opening an issue here to start the modifications required to the W1209 source files prior to doing a Travis CI build to get a binary that I can flash to my W1209.

I have a Travis CI account now which runs either from my Safari web browser or from Terminal on my MacBook Pro running macOS Mojave 10.14.2.

Best regards,

Paul

TG9541 commented 5 years ago

Hello Paul,

I understand that the Travis-CI CLI works on your Odroid. If you clone this repository and follow the Travis-CI Configuration recipe you should be in control of your own STM8 eForth build environment.

I would like to propose doing a test with the ihx file contents in this Travis-CI log (lines 1273-1785).

The next step would be building a lookup table (e.g. with the help of the Forth console). Here are some notes from when I did that.

Reference: https://github.com/TG9541/stm8ef/issues/249:

paulcrawford commented 5 years ago

Hello Thomas,

Actually I did get Travis-CI CLI to work on my Odroid C2 but I could not get stm8flash to make on the C2, so I am going to run every thing on my MacBook Pro on which they both work.

I have forked the TG9541/W1209 repository to my Git Hub account and synchronized it with Travis. Then I edited the .travis.yml file to point to my repository. That triggered a build which was successful. In Travis I can see the log from that build, which has the contents of the zip file for W1209-FD-forth.ihx. Those contents appear to be identical to the one you linked to above. What I do not know how to do is create that zip file so that I can unzip it and upload it with stm8flash. I thought there would be a release file on my Git Hub account that would have the zip file in it but I cannot find it. Can you please advise on how to do this and then I think we are almost there.

Thanks and best regards,

Paul

TG9541 commented 5 years ago

Hi Paul, nice, you've got most of the more difficult stuff working! It's sometimes a bit difficult to assess the kind of skills other people have (we're not in an established industry or trade where roles would set norms).

In my Travis-CI configuration zip files are always created but only published to GitHub Releases when you tag the master branch!

You can either tag, or change the publishing properties (if you figure out how please post it here), or directly fetch the ihx file contents from the Travis-CI log like this:

curl -o - https://api.travis-ci.org/v3/job/456282305/log.txt | awk '/complete - bye!/ {ihx=1}  ihx && /^:/' > W1209-FD-forth.ihx

I don't have to tell you that you have to identify your log URL, but other readers of this issue might need that bit of information ;-)

paulcrawford commented 5 years ago

Hi Thomas,

Success finally.

I could not make the tagging work to automatically upload the .ihx file from Travis to Git but I was able to directly fetch the ihx file from the Travis log but I did have to change more than just the job number in the url. At first that is what I did but nothing got uploaded. Then I noticed that the url above used travis-ci.org while my log was in travis-ci.com. Once I made that change the file downloaded to my computer easily.

I had edited the menu.fs file before the travis build to increase the hysteresis max value from 20 to 80. After I flashed the new ihx file with that change in it, I checked the menu and found I could go up to 8.0°C hysteresis, which means everything is working!

All I need to do now is remove the logging, correct the temperature readings for the 5KR resistor, send the present temperature out on the serial port and change the control from heating to cooling.

Not very much at all, do you think?

Thanks again for all of your help,

Paul

TG9541 commented 5 years ago

Hi Paul,

This project does many things in a rather unusual way and it's great to hear that you got it working! Removing the logger is easy: just comment out lines 31 and 37 in main.fs:

#include measure.fs
#include menu.fs
\ #include logger.fs
#include control.fs

  : task ( -- )
    \ the application runs as a background task
    measure  (       -- theta )    \ measure temperature
    \ logger   ( theta -- theta )    \ data logging
    control  ( theta -- theta )    \ temperature control
    menu     ( theta -- theta )    \ menu and display code
;

Sending the temperature is easy. A variant of the following modification of start in main.fs should do the job:

  : start   ( -- )
    \ start-up word
    init                   \ perform chained init
    [ ' task ] LITERAL BG !
    BEGIN
      theta @ .0 CR
      ?KEY IF 13 = ELSE 0 THEN
    UNTIL
  ;

Pressing <ENTER> should bring you to the console. Please let me know if you need to slow sending down to e.g. once per 10s.

The new 'IDLE feature would work even better (check out the MODBUS code where the server MBPROTO runs as an idle task). As I think about it, it should be possible to make a W1209 with a MODBUS interface.

Changing heating to cooling requires a modification to control.fs, which should be easy to do by inverting the logic.

As for the 5K resistor ... please check if the table @BigVulcanDeal published works for you.

Kind regards, Thomas

paulcrawford commented 5 years ago

Hi Thomas,

Thanks for all of the suggestions. I didn't expect you do all of my work though ;-)...

Anyway, the logger is gone. Simple as you say. Sending the temperature is easy for you. I think I might have struggled to get that change. Probably every 5 seconds would be good to send the temperature as a typical cycle about 300 so about 1.6% error. Not sure I know what you mean by "Pressing should bring you to the console."

For the cooling I have edited control.fs as follows;

\ VARIABLE c.heat VARIABLE c.cool VARIABLE c.delay

: C.off ( -- n ) \ upper threshold [0.1ºC] C.on EE.HYS @ + \for cooling rather than heating need to reverse C.off and C.on \ EE.SET @ ;

: C.on ( -- n ) \ lower threshold [0.1ºC] \ C.off EE.HYS @ - EE.SET @ ;

: controller ( theta -- flag ) \ simple temperature control with hystesis & delay \ c.heat @ IF c.cool @ IF \ ( theta ) C.off SWAP < IF ( theta ) C.on SWAP > IF \ OFF c.heat ! OFF c.cool ! EE.DEL @ ( [10s] ) 20 ( ticks [5ms] ) * c.delay ! THEN ELSE \ ( theta ) C.on < IF ( theta ) C.off > IF c.delay @ IF -1 c.delay +! ELSE \ ON c.heat ! ON c.cool ! THEN THEN THEN \ c.heat @ \ return flag c.cool @ \ return flag ;

: control ( theta -- theta ) DUP DEFAULT = NOT IF DUP controller ( flag ) ELSE 0 ( flag ) \ sensor value undefined: control variable inactive THEN ( flag ) OUT! \ switch relay ;

: init ( -- ) init \ chained init \ OFF c.heat ! OFF c.cool ! 0 c.delay ! ;

Do you think it is OK?

I did review the table that @BigVulcanDeal published but the input (A2) and output (M2:M15) cells he indicated in his comment on HaD did not seem to be linked to anything. I will try to sort that out.

Best regards,

Paul

paulcrawford commented 5 years ago

Hi Thomas,

Travis has been busy doing builds as I have been editing and committing but it is getting an error:

The command "docker run -v pwd:/home tg9541/docker-sdcc:V1.0.1 /bin/sh -c "cd /home && make simload && make zip && cat W1209-FD-forth.ihx"" exited with 2.

This seemed to work fine before but not now. Do you understand why this error is occurring?

Thanks,

Paul

TG9541 commented 5 years ago

Hi Paul,

The docker command failure is possibly because the word (!) > is missing. You can either load it with #require > or do get a bit "Forthy" by taking into account that > is mathematically the same as SWAP < (Polish Notation was originally invented for deductive logic systems, not programming ;-) ).

  : controller ( theta -- flag )
    \ simple temperature control with hystesis & delay
    \ c.heat @ IF
    c.cool @ IF
      \ ( theta ) C.off SWAP < IF
      ( theta ) C.on < IF
        \ OFF c.heat !
        OFF c.cool !
        EE.DEL @ ( [10s] )
        20 ( ticks [5ms] ) * c.delay !
      THEN
    ELSE
      \ ( theta ) C.on < IF
      ( theta ) C.off SWAP < IF
        c.delay @ IF
          -1 c.delay +!
        ELSE
         \ ON c.heat !
          ON c.cool !
        THEN
      THEN
    THEN
    \ c.heat @           \ return flag
    c.cool @           \ return flag
  ;

To figure out why your build fails I need access to the Travis-CI log. That's easiest if you fully integrate Travis-CI into your repo, and also change the URL of the Travis-CI badge in your README.md but you can also simply post the URL of the log here.

If you need results with a rate of about 5s then the 16bit cycle counter TIM, that's incremented with a 5ms rate can be used to generate a "trigger". Capturing that trigger without a state machine is a bit of a race condition but it should work reliably if you constrain the least time it takes to send the temperature string to > 5ms (i.e. more than 5 chars @ 9600 baud):

  : start   ( -- )
    \ start-up word
    init                   \ perform chained init
    [ ' task ] LITERAL BG !
    BEGIN
      ?KEY IF 
        13 = ELSE 0 
      ELSE
        TIM $4F AND 0= IF
          \ must be > 5ms 
          \ => more than 5 chars through signal redundancy
          theta @ DUP .0 .0 CR 
        THEN
      THEN
    UNTIL
  ;

If you need any kind of signal safety I would like to recommend sending TIM and a redundant signal (that's the bread-and-butter safeguard against stalled or corrupt transmission). It would be easy to use CRC16 for that purpose :-)

The nonsensical sentence above is courtesy of "GitHub Flavored Markdown" (the brackets in <ENTER> will be interpreted as invalid HTML elements ;-) - it's been revised).

@BigVulcanDeal pointed out an important weakness in menu.fs: the input key GPIOs are also used for the serial interface. This requires some more state awareness than what's now implemented. I'll be proposing a solution. The menu implementation is also a proof-of-concept for the application of reflection in an embedded application. I guess that most people will need a walk-through.

BigVulcanDeal commented 5 years ago

For whatever value it might have .. here are the routines that I created for the serial interface. Basically, I created a set, get and print method for temperature setpoint, hysteresis, relay delay, and temperature correction .. so 12 commands .. plus a method for print_temp_pv, which would print the current temperature at the serial port .. for a total of 13 new (very simple) words.

That was enough for a useful serial interface. For example, the serial command: 300 set_temp_sp CR would set the temperature setpoint to 30 C. The command print_temp_pv CR would return the current temperature as an easily parsed string, etc.

There was also logic (probably triggered in the "measure" routine) that would call print_temp_pv whenever the temperature reading changed. Since the signal was well filtered, and the system had some "thermal inertia", that worked pretty well.

Basically, this allowed Temperature, Temperature Setpoint, Hysteresis, Correction and Delay to be easily written or read by a Node-Red application over a serial interface, and also allowed for a simple "report by exception" capability. That, in turn, made it easy to report to web connected clients via MQTT (temperature data and a number of other process values in the system were managed this way).

Sample code below .. I know the right thing to do here is to fork and submit, but the computer that I used has been retired .. in fact, this might not be the exact code that I used .. but it's close.

As an aside, the repetitive nature of the methods below highlights the utility of the object oriented abstractions that Thomas invented for the "button GUI" (unfortunately, I never quite had the time to understand that stuff properly).

\ shared accessor functions for stored setpoints etc.

  : set_EE ( value address -- )
     ULOCK ! LOCK
  ;

  : get_EE_raw ( address -- )
      @
  ; 

  : print_EE ( address -- )
      @ .0 CR
  ;   

  \ temperature setpoint access functions

  : set_temp_sp ( new_temp_sp -- )
     EE.SET set_EE
  ;

  : get_temp_sp ( -- temp_sp )
     EE.SET get_EE_raw
  ;

  : print_temp_sp ( -- )
    ." :temp_sp= " EE.SET @ .0 ." ; " CR 
  ;  

  \ hysteresis access functions

  : set_hysteresis ( new_hysteresis -- )
     EE.HYS set_EE
  ;

  : get_hysteresis_raw ( -- hysteresis )
     EE.HYS get_EE_raw
  ;

  : print_hysteresis ( -- )
     ." :hysteresis= " EE.HYS @ .0 ." ; " CR 
  ;

  \ relay delay time access functions

  : set_delay ( new_delay -- )
     EE.DEL set_EE
  ;

  : get_delay ( -- delay )
     EE.DEL get_EE_raw
  ;

  : print_delay ( -- )
     ." :delay= " EE.DEL @ .0 ." ; " CR 
  ;

  \ temperature correction access functions

  : set_correction ( new_correction -- )
     EE.COR set_EE
  ;

  : get_correction ( -- correction )
     EE.COR get_EE_raw
  ;

  : print_correction ( -- )
     ." :correction= " EE.COR @ .0 ." ; " CR 
  ; 

#include measure.fs
#include menu.fs
\ #include logger.fs
#include control.fs

 \ temperature process value accessor
  : print_temp_pv ( -- )
    ." :temp_pv= " measure .0 ." ; " CR 
  ;
paulcrawford commented 5 years ago

Hi Thomas,

First of all, I have to say that your support for both stm8ef and W1209 is incredible. Thank you so much.

On the docker error, I have not edited .travis.yml except to change deploy.on.repo from yours (repo: TG9541/W1209) to mine (repo: paulcrawford/W1209) and that was done before I had successful builds on Travis, so I don't know how there is suddenly a problem with it. Where would I put "#require >"?

I looked at your revision for control.fs and I think I see the reasoning behind it. Once I get the temperature working a simple test will verify that all is well.

The URL for latest failed build on Travis is: https://api.travis-ci.com/v3/job/173245925/log.txt

On sending the theta value on the serial port, your suggestion looks fine (but what do I know? ;-)). I really only need one character to send theta since it will normally be about 60 to 70 (6.0°C to 7.0°C) and if something has gone wrong about 250 (25.0°C). That can all fit in an unsigned char. The rest can be filler and a CRC (I do normally use CRC on all my serial transmissions, of which I have five on the Odroid C2 now).

The way that my particular W1209 will be used, virtually all of the time the input key GPIOs would be doing serial TX. The menu will accessed only very rarely. Obviously at the original setup, but there is likely no need to change any of the parameters once that is done. I trust that that should make things a little easier.

Thanks again for everything and I look forward to your response.

Best regards,

Paul

TG9541 commented 5 years ago

Hi Paul,

The #require >, if you need it, would go right after the word NVM (i.e. it has to be compiled to Non Volatile Memory, not to RAM).

The error in the Travis-CI run is this:

TX: \#include logger.fs
error \#include logger.fs \#include?

In Forth a comment is simply the word \ that instructs the interpreter/compiler to skip the rest of the line. Like any other word (and unlike // in C ) \ must be separated by white-space. After inserting a blank, the error should go away (\ #include logger.fs).

You can, of course, send a binary value with a (binary) CRC even if I'd prefer parsing an old fashioned human-readable string with sscanf (which would stop an endianness discussion before it even begins ;-) ).

For a moment I thought about using MODBUS replies, but I guess that I'll write a quick hack for you and integrate it into your fork.

By the way, thanks for the approval :-)

Kind regards, Thomas

paulcrawford commented 5 years ago

Hi Thomas,

In the end I chose the "Forthy" way with SWAP <. You had used already, of course, but I did not understand why before. Now I do.

I also now understand about "\ " for comments. There were a few others lurking in my revisions but they are all gone now. Too used to "//" in C as you say.

Thanks also for helping me understand how the log.txt file identifies errors. That is invaluable.

Once I got over all of those issues, everything fell into place including the theta value coming out on the serial port. Presently, however, it seems to come out virtually continually rather than once every 5s. the following file capture shows the data with relative time stamps: CoolTerm Capture 2019-01-31 15-16-09.txt

Perhaps you can suggest how to reduce the frequency. The present code is:

: start ( -- ) \ start-up word init \ perform chained init [ ' task ] LITERAL BG ! BEGIN theta @ .0 CR ?KEY IF 13 = ELSE 0 THEN UNTIL ;

I also went back to the comment from @BigVulcanDeal on HaD and clicked on the link to the correction table for the 5KR pull-up resistor. It seems that the Google Docs worksheet has been updated and now does have the correct data in column M. So I copied and pasted the values into measure.fs and did another build. That brought the display value from about -10°C to about 21°C which is about correct for room temperature at my desk. As @BigVulcanDeal noted, it is possible to the use EE.COR to fine tune the value by calibrating against a known temperature.

So that is almost everything done on my TODO list. The one issue I found though is that will all of the data coming out of the serial port at such a fast rate the keys have become useless as you suggested. That is really not a problem for me as I really do not need to change any parameter values as I can simply set the defaults to what I want and do a build.

The second issue is in control.fs. I cannot seem to get control of the relay. At first I could not seem to get it to come on, but now I cannot get it turn off i.e. the red LED is on all of the time. This is the code for the parameters:

LAST @ ( -- na M.end ) \ max min address def \ 100 0 EE.LOG 10 >MENU LOG. \ [0.1h], 0: off 600 0 EE.DEL 0 >MENU DEL. \ [0.1s] 20 -20 EE.COR 0 >MENU COR. \ [0.1C] \ 40 1 EE.HYS 10 >MENU HYS. \ [0.1C] 40 1 EE.HYS 40 >MENU HYS. \ [0.1C] \ 800 100 EE.SET 375 >MENU SET. \ [0.1C] \ 100 30 EE.SET 70 >MENU SET. \ [0.1C] 400 200 EE.SET 290 >MENU SET. \ [0.1C] LAST @ CONSTANT M.START

These values are for test only but EE.HYS is 40 for a 4°C deadband on the control while EE.SET is 290 for a 29°C trigger point. This should mean that if theta is greater than 290 then the relay should come on to start the cooling. Once theta drops to 250 then the relay should turn off to stop the cooling. I have raised the temperature to above 290 by holding the probe in my hand and then reduced the temperature to below 250 by putting the probe on an ice cube but all of the while the red LED and relay are on.

This my latest control.fs:

https://github.com/paulcrawford/W1209/blob/master/control.fs

It looks to me that if flag is 0 then the relay should go off via OUT! or if flag is -1 then the relay should come on via OUT!. But presently it never goes off.

Perhaps you could look at my control.fs to see if you can find anything that does not look right?

If we can resolve this control issue and perhaps reduce the serial port TX frequency, I will be ready to integrate the W1209 with eForth into the rest of my project.

Thanks again for your persevering assistance.

Kind regards,

Paul

TG9541 commented 5 years ago

Hello Paul,

first of all, kudos for a visiting the exotic country of Forthlandia (rumor has that there are dragons ;-) ). It looks like you're doing great!

I looked into the different questions and issues:

Serial data stream

How about an output with temperature, 16bit life counter and CRC16?

 18.9 85 A351
 18.9 86 A211
 18.9 87 62D0
 18.8 88 A6C1
 18.8 89 6600
 18.8 8A 6740
 18.8 8B A781

The transmission rate is 2.5s, and the transmission can be stopped by pressing <enter> (e.g. for using the CLI that @BigVulcanDeal posted above).

The core of the output loop looks like this:

    0  ( cc ) \ counter
    BEGIN
      TIM $1FF AND 0= IF
        1+
        ( cc ) -1  theta @ DUP  .0 crcw
        HEX
        ( cc crc ) OVER    DUP  .  crcw
        ( cc crc ) . CR
        DECIMAL
      THEN
      ?KEY IF 13 = ELSE 0 THEN
    UNTIL

crcw applies the common CRC-16 (polynomial 0x8005, seed 0xFFFF, high-byte first).

Controller issues

Since your controller works fine for me it's likely that you didn't reset the EEPROM contents to defaults (please press and hold the + and the - keys for a short while together - if rES. appears the EEPROM values have been reset).

Menu issues

This was a real bug in my code and it required some advanced trickery to fix without changing the W1209-FD STM8 eForth binary.

The problem was this: TxD and the - key use the same port. Unfortunately I never really understood that my assumptions about my own code where wrong: unlike the SWIMCODE code TX! never cares about the port direction.

Here is a work-around that wraps TX! so that the GPIO is orderly shared with the menu key:

  : m.TX! ( c -- )
    [ 1 PC_DDR PNTX ]B!  2 m.tx !
    TX!
  ;

  : menu ( theta -- theta )
    \ work around GPIO dual use effects
    m.tx @ ?DUP IF
      1- m.tx !
    ELSE
      [ 0 PC_DDR PNTX ]B!

      \ menu code with time-out handling
      M.timer 0= IF
        \ time-out sub menus
        L' M0 m.level !
      THEN
      m.level @ EXECUTE
    THEN
  ;

  : init ( -- ) init    \ chained init
    M.rh                \ reset hold
    M.START m.ptr !     \ point to the first menu item
    0 m.time !          \ time-out -> menu init
    [ ' m.TX! ] LITERAL 'EMIT ! \ work-around W1209 key GPIO doubling as TxD
  ;

Unfortunately, I forgot to fork you repo and cloned it instead. Please apply the following patch to your branch:

0001-fixes-2-TX-GPIO-work-around-CRC.patch.zip

Kind regards, Thomas

paulcrawford commented 5 years ago

Hello Thomas,

Well Thomas, you have outdone yourself once again! I don't know how you manage it but everything is perfect now.

I do have to admit that I did have some experience with Forth in the late '80s. The company I worked for then had a control device that used Forth. At one stage I was managing and modifying the source code that a colleague had originally developed. Once you get used to it, it is a fantastic language to work with. For real time control, as we used it back then, it is probably unparalleled.

Anyway, back to the W1209. I put in the source code you wrote for the Serial Data Stream and did another build. It works perfectly. I just need to write some code for the ATMega328P that will be receiving the serial data and checking the crc16 bytes.

You were also spot on with the controller issue. A simple reset fixed everything. I did see that in the documentation but it did not really click with me then. It will never get missed again...

The menu fix also works perfectly. The serial data simply pauses when the keys are pressed. Without that change, any modification of the parameters required a rebuild so this is much, much better.

Since my application is for cooling and a Peltier cooler can only achieve a temperature reduction of about 20°C, I have made the set point for control 7°C, which with a deadband (hysteresis) of 1°C provides for operation of the cooler only between 7°C and 6°C. Through some preliminary calibration I have found that in this range the temperature probe AtoD conversion is not that accurate, with the probe reading maybe as much as 2°C lower than the actual temperature. That would mean that the actual temperature range controlled would be 9°C to 8°C. Not good for a cooler trying to keep food cool. So, once I have the proper calibration done I will simply use the EE.COR value via the menu to adjust the theta measured.

BTW, I did all of code modification by hand using the contents of your patch but I am sure that there is an automated way to apply the patch. How does one go about doing that? I am really not that knowledgeable on using Git Hub yet...

Thanks again for all of your effort above and beyond...

Warmest regards,

Paul

TG9541 commented 5 years ago

Hello Paul,

I'm glad that it worked! My first contact with Forth was in the early 80s - in my early career I really should have used it instead of programming in C like everybody else. It would have saved me a lot of time in the years when I worked in "embedded control"! I'm now considering using it for advanced test systems but I don't nurture any illusions here: "engineering cultures" are very difficult to change.

If you intend to process the serial output with an ATMega328p it's maybe better to use binary data representation as you proposed initially. Maybe sending a HEX encoded temperature value (instead of fixed point decimal) can be used as a compromise. The CRC-page I referenced above should provide usable C code (there is also a nice "test feature").

Regarding the temperature calibration problem: the interpolation word @inter is very versatile. Creating a "correction function" costs almost nothing :-)

Regarding the patch: applying git generated patch files is very easy: just search for "git apply patch".

It's been fun working with you on this little project. If you have new ideas or a new interesting "problem" don't hesitate to present it! Please make sure you "star" the STM8 eForth repos and spread the word (for tiny projects search engines matter :-) ).

Best regards, Thomas

paulcrawford commented 5 years ago

Hello Thomas,

I want to provide a brief background as to why I am doing all of this work at all and to bring you up-to-date on my calibration for the W1209.

First, the background. I used to have a 22m Dutch barge converted to a live aboard. It had a rather small refrigerator, so to supplement its capacity I got a cooler with a 12V Peltier cooling module. The cooler was used to store fruit, vegetables, drinks, and other things that needed to be cool but not easily spoiled such as milk. This approach worked well for the 20°C temperature decrease from ambient that the cooling module could create since the barge was used mainly in the spring and autumn. There were a couple of issues though:

  1. The Peltier module ran continuously drawing about 4A on the 12V house batteries. This base load contributed to a reduced time period that the barge could run on batteries before having to be charged.
  2. If the weather became cooler while I was on board, the temperature in the cooler might get to 0°C, or less, which resulted in frozen and ruined fruit and vegetables.

Using the W1209 temperature controller solves both of the above issues since the module duty cycle reduces both the average current consumed as well as the base load current and prevents freezing spoilage by not allowing cooling operation when it is not needed.

On the calibration, I first decided to get the 0°C temperature digital bits determined as it is fairly easy to do. I have a digital kitchen thermometer which is reputed to be quite accurate so I tie wrapped the W1209 probe to the end of its probe and placed them both in a glass of crushed ice and water. The kitchen thermometer read about 0.2°C, quite close to 0°C while the W10209 read about -3.4°C. Based on that I changed the calibration table in measure.fs so that when I checked again to confirm both probes were acceptably close to 0°C. I had also checked the two probes at approximately 20°C by placing them in a glass of water that was in equilibrium with the room. Again both read very close to 20°C.

Unfortunately, of course, my temperatures of concern are neither 0°C or 20°C but 6°C to 7°C so another calibration had to be done for the 100 (10°C) value in the calibration table. This was done by running the cooler with the set point of 7°C and hysteresis of 1°C and placing the kitchen thermometer in the bottom of the cooler, near the W1209 probe. When the W1029 turned on or off, I opened the cooler and immediately read the kitchen thermometer. Then I estimated the change in digital bits needed to bring the two into agreement. The first guess was to increase by 1000. I made the adjustment in measure.fs and checked again. The next guess was to reduce the bits by 100. That final value seemed to be acceptably close. The original calibration values by @BigVulcanDeal using the 5k1R resistor for 10°C and 0°C were 25565 and 26509, respectively. My final values were 26498 and 28088, respectively.

I did try another W1209 temperature probe with the same calibration table and placed it in the ice bath and it was again about -2°C. This suggested that the QC on the probes is not that good in terms of repeatability but then this is not high grade industrial equipment either. I only paid CDN$1.79 for a whole W1209 including the temperature probe. It also means a custom .ihx file for each individual probe and board combination. Tedious but it can be done.

The W1209 board as heating controller may be an easier task but it should probably be checked with a precision thermometer in a temperature controlled water bath if the actual temperatures are critical. This kind of equipment is a little beyond what the average hobbyist can afford.

Back to the cooling application though, the duty cycle for the controlled Peltier cooling module at an ambient temperature of about 20°C was approximately 7 minutes on and 5 minutes off between 7°C and 6°C so about 58% running. This in turn reduces the base load on the batteries by the full 4A but adds a variable load averaging 2.3A. Reducing the base load is very important because of the Peukert effect on drawing current from a lead acid battery. So that essentially solves the first issue.

The second issue is also solved since with cooler ambient temperatures the temperature inside the cooler will not go below 6°C unless of course the ambient temperature is well below 6°C.

I do have a question about the crc code that you provided. When I put the hex bytes sent into the online crc generator I do not get the same value that is sent with the data. For example, when put the following hex data into the online generator for crc16, 20 32 36 2E 31 20 35 35 30 43 20 ( which represents " 26.1 550C ") I get a crc of 0x4c62 while the crc that came with the above data was 38 43 32 45, which I believe represents 0x8C2E. Am I doing something wrong here? Are the spaces (0x20) included in the crc calculation? If I take the spaces out, the online crc gives 0x77E5 so it seems that is not the case.

BTW, I have starred both W1209 and stm8ef.

Thanks again for everything.

Paul

TG9541 commented 5 years ago

Hello Paul,

sorry for the delay - these days I work longer hours than I normally do.

Thanks for explaining your use case!

NTC sensors have different accuracy grades - the ones used in cheap products most likely don't have the best accuracy, and even the best grade is considerably less accurate than e.g. PT100, KTY-10, or cheap linearised digital sensors.

It's possible to patch the calibration table with a small Forth script (and it would also be possible to store it in the EEPROM).

The W1209 board as heating controller may be an easier task but it should probably be checked with a precision thermometer in a temperature controlled water bath if the actual temperatures are critical. This kind of equipment is a little beyond what the average hobbyist can afford.

I'll be building something based on DS1621 sensors with I2C interface. The thermometer error of these chips is about 0.5K (0.9°F), and they're cheap: I got 5pcs for $1.53. The chips even have an alarm output that can be used as a simple digital thermostat (much like a W1209).

I do have a question about the crc code that you provided. When I put the hex bytes sent into the online crc generator I do not get the same value that is sent with the data. For example, when put the following hex data into the online generator for crc16, 20 32 36 2E 31 20 35 35 30 43 20 ( which represents " 26.1 550C ") I get a crc of 0x4c62 while the crc that came with the above data was 38 43 32 45, which I believe represents 0x8C2E. Am I doing something wrong here? Are the spaces (0x20) included in the crc calculation? If I take the spaces out, the online crc gives 0x77E5 so it seems that is not the case.

You're doing the CRC based on the ASCII string - the one I calculate is based on the fixed-point binary representation of "26.1" (261 = 0x0105 -> 0105550C -> CRC-16-MODBUS 0x8C2E = ASCII 38 43 32 45).

When I proposed the encoding I assumed that you use a Raspberry PI (or a similar powerful µP) on the receiver side. There, a Python script (or a C program with sscanf) could easily decode the character strings.

If you like I can encode the data as a fixed length binary string - a pause between characters longer than, say. 500ms would mean "EOL", which should be easy to detect.

BTW, I have starred both W1209 and stm8ef.

Thanks a lot :-) Kind regards, Thomas

paulcrawford commented 5 years ago

Hello Thomas,

I was reviewing again the CRC-16-MODBUS calculations for the W1209. When I take data that comes out of the W1209 on the serial line and run CRC16 interactively on the W1209 I can get the CRC value that matches the online CRC calculator value. For example, the W1209 outputs "20.5 5B0 3F93". 20.5 becomes "CD" in hex so the first interactive command and result is: "CD FFFF CRC16 . D57E ok". Then the next interactive command and result is: "5 D57E CRC16 . 2395 ok". And finally the last is: "B0 2395 CRC16 . DBE2 ok". (I know I should learn how to do this in one line in eForth, but at least I am getting the right answer.) Putting CD05B0 into Lammert's CRC online calculator gives "DBE2" for CRC-16 (Modbus). So there is complete agreement. But when I look again at the CRC value coming from the W1209 it is: "3F93". This suggests that if I calculate the CRC value in the receiving device based on the data received I will always have the wrong value to compare with. I have done the same comparison probably about 6 times and always get a difference. I recompiled my source code again using Travis and flashed the W1209 again to ensure that any changes I had made to the Forth code interactively were overwritten, but still the results are the same.

Can you see any errors in the way I have done the comparisons? Or is there something in the CRC value coming from the W1209 that I am not interpreting correctly? Does "DBE2" really equal "3F93"?

Best regards and Happy Easter,

Paul

paulcrawford commented 5 years ago

Hello Thomas,

In a previous response on Feb 2 you stated: "crcw applies the common CRC-16 (polynomial 0x8005, seed 0xFFFF, high-byte first)."

"CRC-16" was a link to Lammert's site. While he does show the polynomial 0x8005 for CRC in the table at the bottom of https://www.lammertbies.nl/comm/info/crc-calculation.html, if you go to the code at https://github.com/lammertb/libcrc/blob/master/include/checksum.h you will see: #define CRC_POLY_16 0xA001

but

#define CRC_POLY_SICK 0x8005

I have checked your definition of CRC16: : CRC16 ( n c -- n ) \ CRC-16-ANSI (seed with -1 for Modbus CRC) XOR DOXCODE [ $A608 , \ LD A,#8 $54 C, \ 1$: SRLW X $2407 , \ JRNC 2$ $01 C, \ RRWA X ; XOR X,#0xA001 $A801 , \ XOR A,#0x01 $01 C, \ RRWA X $A8A0 , \ XOR A,#0xA0 $01 C, \ RRWA X $4A C, \ 2$: DEC A $26F3 , \ JRNE 1$ ] ; and it appears to use the correct polynomial, 0xA001.

So it seems that the table on Lammert's page is a little misleading.

I already have c code to deal with CRC16 Modbus, which is what you use, so everything works except getting the right CRC value as noted in my previous comment.

Thanks,

Paul

TG9541 commented 5 years ago

Sorry for the late reply - I was on a family visit. Will look at it shortly!

paulcrawford commented 5 years ago

Hello Thomas,

I am sure that you are very busy but do you have a few moments to review my issue?

Thanks,

Paul

TG9541 commented 4 years ago

@paulcrawford I was indeed very busy and then forgot to check the still open issues. Sorry about that.

Please let me know it if you still need a solution to the problem!

paulcrawford commented 4 years ago

Hi Thomas,

Thanks for remembering this. I did figure it out on my own and all is well with you code. When I was doing the crc calculation I left out a leading 0 on a byte. Numerically it would make no difference but in a crc calculation it makes all the difference in the world of course. I always seem to learn the hard way!

Best regards,

Paul

Sent from my iPhone

On Jul 16, 2020, at 12:13, Thomas notifications@github.com wrote:

 @paulcrawford I was indeed very busy and then forgot to check the still open issues. Sorry about that.

Please let me know it if you still need a solution to the problem!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

TG9541 commented 4 years ago

Hi Paul,

thanks for the info! I'll be closing the issue now :-)

Stay safe! Thomas