TG9541 / stm8ef-modbus

A lightweight framework for MODBUS RTU nodes in STM8 eForth that can do more than just I/O
https://github.com/TG9541/stm8ef/wiki/Board-C0135
MIT License
32 stars 12 forks source link

Relays not switching #12

Closed tealbrains closed 4 years ago

tealbrains commented 4 years ago

Hi Thomas,

I know pretty much next to nothing when it comes to eForth. I did not know what it was until a couple of days ago when I was trying to see if there would be a better firmware for the 4 relay board (it seems the newer ones have a "DAT" pin next to "SWIM" pin and are labelled "v1.2", mine has an STM8S003F3 on it).

Kudos for all the great work!

Now to my problem: I have flashed the device and loaded the modbus files of this repo successfully after doing that diode mod. My terminal application on the PC can talk to the device via a USB-RS485 adapter, but the "Write Single Coil" function is not activating the relays. Is there anything extra that needs to be done after the "make load" to get them working?

I don't think I will be diving too deep into eForth, I just needed a good reliable firmware that would respect the timings of modbus RTU the original firmware was completely ignoring.

Any ideas?

TG9541 commented 4 years ago

Kudos back to you forgetting this far!

So far, as strange as it sounds, I concentrated on testing the protocol and did little to do the last step, namely implementing the basic I/O functionality for the relay board. Also I had planned to use the new "modular build" to provide configurations for the tiny STM8S001J3 board and for the C0135 relay board. That's easy enough, I just didn't do it.

I guess that it's high time that I look at some unfinished things :-)

Questions:

  1. What's your board configuration?
  2. Which GPIO do you use for the console?
  3. What do you use for issuing MODBUS commands?
  4. Can you share it?
tealbrains commented 4 years ago

Thanks for your prompt reply!

  1. The configuration as in hardware pins? I think it has the same pinout as the earlier model as listed here : https://github.com/TG9541/stm8ef/wiki/Board-C0135 . The relays seem to go to the same pins and the modbus pins are already confirmed as being the same pins. I just flashed the default configuration of the repo but passed stm8s003?3 as argument for stm8flash.
  2. For the eForth console the SWIM pin worked with a diode to produce the other serial line.
  3. I have been using QModMaster on Windows for this. There is a precompiled version and I just wanted something to test things quickly. I believe you can compile/use it under Linux but you have to figure it out.
  4. https://sourceforge.net/projects/qmodmaster/
TG9541 commented 4 years ago

First step: a C0135 binary with PD1/SWIM console:

I used the C0135 board folder and used the following serial interface definition in globconf.inc:

        HALF_DUPLEX      = 0    ; Use UART in half duplex mode
        HAS_RXUART       = 0    ; No UART RXD, word ?RX
        HAS_TXUART       = 0    ; No UART TXD, word TX!
        HAS_RXSIM        = 1    ; Enable RxD via GPIO/TIM4, word ?RXGP
        HAS_TXSIM        = 1    ; Like HAS_RXSIM, word TXGP!, use for console if > HAS_TXUART
        PSIM     = PORTD        ; Port for UART simulation
        PNRX             = 1    ; Port GPIO# for HAS_RXDSIM
        PNTX             = 1    ; Port GPIO# for HAS_TXDSIM

Here is the board binary I'm now using: C0135.zip

OUT! should work now ($1f out! should switch on all relays and the LED).

The next step will MODBUS coils output for C0135 relays.

TG9541 commented 4 years ago

When using the C0135 binary from my last comment and the following code at the end of MBSERVER switching relays with qmodmaster works:

  \ Proto and I/O handler
  :NVM
     MBPROTO
     coils @ out!
  ;NVM ( xt )

  \ --- MODBUS server startup

  : MBSERVER ( -- )
    0 coils !
    ( xt ) LITERAL 'IDLE !
  ;

This is my current binary - it worked OK with full-duplex serial and with my own RS485 interface: C0135-readflash.zip

So far I didn't have any luck with my CH340 based Green+Black RS485 dongle.

@tealbrains could you please test if the binary works with your RS485 adapter? On Linux, flashing should work with the following command: stm8flash -c stlinkv2 -p stm8s103f3 -s flash -w out/C0135/C0135-readflash.ihx

EDIT: I just got it working with the "Green+Black" - strange since I didn't change anything. So far there are no errors in scan mode.

tealbrains commented 4 years ago

I have been able to test a few things. Here are my findings:

[About your first answer]

1) I was not using full-duplex and had BOARD set to SWIMCOM in the Makefile. I changed that to C0135. After that I could start using the full-duplex serial port exposed on the board instead of the SWIM pin for the eForth terminal, which I used to upload the files again with make load.

2) After issuing words to check the eForth terminal was working I proceeded with a $1f out! , which turned all the Relays ON as you described.

[Next post]

3) The latest binary you included C0135-readflash.ihx seems to be missing the full-duplex serial, I had to go back to using the SWIM pin.

4) I have made sure I have those lines you added in MBSERVER but I am getting the following after trying to upload the files with make load :

ln -s out/C0135/target target
tools/codeload.py -b out/C0135 -p /dev/ttyUSB0 serial main.fs
Uploading main.fs
#require MBSERVER: skipped
TX: 
TX: 2 CONSTANT BAUD9600
TX: 
TX: NVM
TX: \ --- MODBUS server startup
TX: 
TX: : init ( -- )
TX: BAUD9600 UARTISR
TX: 1 mbnode !
TX: MBSERVER
TX: ;
TX: 
TX: ' init    'BOOT !
TX: RA
tealbrains commented 4 years ago

@TG9541 Maybe the binary you shared is not the correct one?

When I issues make flash I get about 4kB of binary. The latest you have shared seems to be the full flash size of 8kB.

TG9541 commented 4 years ago

@tealbrains: you're right, the binary you've been using is the old one. I shared two new ones, one "C0135-with-PD1/SWIM-console" and one with "basic MODBUS-with-Relays". I certainly made too many non-communicated assumptions :-)

The C0135 I'm now working on is a "board folder" in the STM8EF-MODBUS, and it's not the same as the C0135 in the STM8 eForth repository. The "modular build feature", which is work-in-progress, compiles a fresh board binary instead of using one from the "STM8 eForth Binary Release". You'll have to make some manual steps until the solution is fully automated (help would be appreciated, but I think I can get it done in the next days).

Here are the steps that worked for me:

  1. un-zip the board folder in the comment above into your project folder
  2. run the make command documented in the README.md: make -f forth.mk BOARD=C0135 3 flash it to your board with stm8flash -c stlinkv2 -p stm8s103f3 -s flash -w out/C0135/C0135.ihx
  3. edit your Makefile to use C0135 (it will use the new C0135 if out/C0135 is present)
  4. make sure target is a symlink to out/C0135/target
  5. run make load

You can skip steps 1 and 2 if you replace the C0135 binary the STM8 eForth with the new C0135 binary in the comment above (this one will provide a PD1/SWIM console).

As I said, this is work in progress, I'll finish the "modular build" as soon as the MODBUS features work. I'll push my changes in a bit.

TG9541 commented 4 years ago

The commits implement some things that were missing:

Please note that the modular build is yet to be fully implemented. Please use the work-around above.

tealbrains commented 4 years ago

@TG9541 I now understand the process and what you are trying to achieve with the modular build.

I have compiled the binary as per your latest instructions (I had to install sdcc). The eForth terminal works and I am able to control the relays with the $1f out! command, but unfortunately RS485/modbus is now not working with QModBus for some reason and I have double-checked my wiring (which seemed to be working fine with the the older firmware not targeting C0135 as QModBus was able to communicate to the STM8, but there was no relay control). Is there a pinout configuration issue maybe?

I understand that the RS485 uses PD6 for Rx on header so we can't have full duplex for the eForth terminal and have to use the SWIM pin but it looks as if the RS485 is now maybe conflicting with something?

tealbrains commented 4 years ago

The commits implement some things that were missing:

* node ID from $4000 in EEPROM

* baud rate from $4002 in EEPROM (0: default 9600 baud, see comment [here](https://github.com/TG9541/stm8ef-modbus/blob/dd1f0aa228b19231815097a4d5a849d84660346a/UARTISR#L4))

* FC03 "Read Holding Registers" can read EEPROM

* FC06 "Write Single Register" implemented

* holding register words 0..1023  are EEPROM (STM8S103: 320 words, STM8S103: 512 words, STM8S207: 1024 words)

* holding register words 1024+ are variable `holding`

* FC16 "Write Multiple Registers" only partially implemented for now

* input (`mbpre`) and output (`mbact`) action handlers can be used for I/O (e.g. relais)

Please note that the modular build is yet to be fully implemented. Please use the work-around above.

I have a couple of questions/observations around this update. 1) I think that for my v1.2 board which has the STM8S003, the EEPROM size is 128 Bytes 2) It's good that you put the address of the device in EEPROM, does it start with "0x01" by default instead of "0XFF" if device is in virgin state from factory?

TG9541 commented 4 years ago

I have compiled the binary as per your latest instructions (I had to install sdcc). The eForth terminal works and I am able to control the relays with the $1f out!

That's good - at least the compilation works. I'm thinking of doing this with the help of build-automation so that any user can download a ready-made binary for the C0135.

command, but unfortunately RS485/modbus is now not working with QModBus for some reason and I have double-checked my wiring (which seemed to be working fine with the the older firmware not targeting C0135 as QModBus was able to communicate to the STM8, but there was no relay control). Is there a pinout configuration issue maybe?

This shows that there is no hardware issue with V1.02. It's more likely something on the Forth side or with the configuration.

I understand that the RS485 uses PD6 for Rx on header so we can't have full duplex for the eForth terminal and have to use the SWIM pin but it looks as if the RS485 is now maybe conflicting with something?

Technically it might be possible to have alternating Forth and MODBUS activities, although the only thing I can think of where the console wouldn´t get jammed by MODBUS is PD5-half-duplex mode. I've also been thinking of a console through MODBUS (but so far I had difficulties with the direction control).

I have a couple of questions/observations around this update.

1. I think that for my v1.2 board which has the STM8S003, the EEPROM size is 128 Bytes

As far as hobby applications are concerned the STM8S003 is the same chip as the STM8S103 - only the specs differ. I've yet to see the first one that has less than 640 Bytes EEPROM, or that is dead after 10000 Flash cycles, or that doesn't have the Unique-ID feature. The STM8S103 has some more interesting features if you look closely.

2. It's good that you put the address of the device in EEPROM, does it start with "0x01" by default instead of "0XFF" if device is in virgin state from factory?

I didn't think of that - that's a problem indeed. You can do the following as a work-around:

#require LOCK
#require ULOCK
ULOCK
1 $4000 !
0 $4002 !
LOCK

What do you think of a "preset feature", e.g. "Press and hold the user key for > 5s" for resetting Node-ID and baud rate?

What do you think about a "traditional mapping" of coils/input/holding registers in a holding address space? The EEPROM and the Flash ROM could have a distinct offset.

tealbrains commented 4 years ago

Technically it might be possible to have alternating Forth and MODBUS activities, although the only thing I can think of where the console wouldn´t get jammed by MODBUS is PD5-half-duplex mode. I've also been thinking of a console through MODBUS (but so far I had difficulties with the direction control).

I think this is likely too much trouble. It would only make life easy for debugging the application (leaving the programmer connected and having eForth OR Modbus) instead of having to connect/disconnect/connect, etc. Once it is is programmed, if you want Modbus and eForth it just makes sense to use the SWIM pin like you are doing now as it is not used... The v1.2 board has this "DAT" pin next to SWIM. I can trace where it goes if you want. That could maybe provide a full-duplex for this board. I think you already have a working solution so probably low prio... I personally won't be using eForth once Modbus is working. It's a nice interface though :) maybe that over RS485 would be quite powerful but you are right, depending on what you can get via eForth it would potentially have to be a completely different protocol as direction control could be problematic, you would have to specify "windows" for master RX for example.

What do you think of a "preset feature", e.g. "Press and hold the user key for > 5s" for resetting Node-ID and baud rate?

I think that is a great idea and would not require any hardware as the board already has buttons. If you chain several nodes you can basically set one at a time this way, then it would be up to the developer to write the new address via the master.

What do you think about a "traditional mapping" of coils/input/holding registers in a holding address space? The EEPROM and the Flash ROM could have a distinct offset.

That sounds good too. You can probably limit this to a minimum given the number of pins this board has, something to hold the status of the "Coils" (Relay and LED), something for the spare pins maybe... I think 99% of people would use this just for the relays.

TG9541 commented 4 years ago

The v1.2 board has this "DAT" pin next to SWIM. I can trace where it goes if you want. That could maybe provide a full-duplex for this board.

Please trace it, at least for updating the docs (for some users a console through this pin may also be viable). It would also be possible to have a full-duplex console through PA1-PA2 since the 8MHz crystal is currently unused.

I can also think of providing something like DOUBLECOM, where the user can decide which interface to use for the console. That way it would be possible to program the device through the UART and at the end switch the console to PD1/SWIM.

I think you already have a working solution so probably low prio... I personally won't be using eForth once Modbus is working.

I was thinking of running local control through Forth - the MODBUS master would then interact with something that runs fast, also interactive, logic locally. For example, @bademux had the idea of connecting light switches to the inputs so that relays can be controlled locally without any noticeable delay. The MODBUS master would then read COILS to learn about the new local state and manipulate it as needed. Another example is a local thermostat that receives a set-point through a holding register, and from which the MODBUS master could collect data. The beauty of such solutions is that they provide the basic feature even if the master or the connection has issues. Spouses and other significant stakeholders of home automation will appreciate reliable performance ;-)

tealbrains commented 4 years ago

Yes I can see why there would be value there.

I have just probed the board to see where the "DAT" labeled pin is going, and it goes to VCAP (pin 8). So no use for it as GPIO... I am not even sure why they would have it exposed and labeled as such. Maybe there is another uC in the family that actually has a GPIO instead of VCAP?

TG9541 commented 4 years ago

@tealbrains: the only explanation I can offer is that the designers of the relay board prepared for using the Nuvoton MCS-51 style chip. That "pin-compatible component" has an extra GPIO in place of the STM8S Vcap. I hope that they won't use it since without a hot-air rework tool the µC would be very difficult to replace.

I've got the modular build working. A minor adjustment will be needed to the STM8 eForth build tools to make it work with multiple board folders. Will push that shortly.

By the way, what's your time zone?

TG9541 commented 4 years ago

Deploying in GitHub Releases works - almost. I need to update the credentials (later on).

@tealbrains: running make will now compile, flash and load. Maybe that's a bit too much :-)

tealbrains commented 4 years ago

@TG9541 Sounds great! I will be testing in the morning and report. My timezone is AEST :)

TG9541 commented 4 years ago

There was a fat bug in one of the scripts of STM8 eForth which broke 'IDLE that made it into today's STM8 eForth pre-release 2.2.24.pre2 (refer to https://github.com/TG9541/stm8ef/issues/300 ).

If you already made a make clean && make with 2.2.24.pre2, please pull and start over with make clean.

I just tested the C0135 binary in releases - it works for me.

tealbrains commented 4 years ago

I tested the new release (building from code) and most things seem to work. Here are my observations:

1) The make for everything does not work too well because the SWIM pin used for uploading code (with the STLink) is also used for make load (with a Serial to USB adapter). The make breaks and throws and error, and I subsequently have to manually issue the command contained in make load : tools/codeload.py -b out/C0135 -p /dev/ttyUSB0 serial C0135/board.f. If the connections did not need to be modified between the two commands then the universal make would work but not in this case.

2) I can control all relays via the eForth terminal but I am still not able to talk to the device using modbus.

TG9541 commented 4 years ago

What works for me is a simple wired-or of the ST-Link SWIM pin and the serial interface 2-wire-hack-device (i.e. TXD sink-only with diode). I should have mentioned that.

It's surprising that communication doesn't work. Would you mind giving the hex file in the releases a try?

Please enter the following before testing with "Node-ID 1":

ULOCK
1 $4000 !
0 $4002 !
LOCK

I also tested with 19200 baud and different Node-IDs (qmodmaster sometimes needs to be reminded of settings).

tealbrains commented 4 years ago

@TG9541 I should have added a second wire straight to SWIM when I added that diode + wire.. for the other direction.

Entering the commands to set the slave address worked (sorry I forgot about this step!). Modbus is now working as expected! Thanks :) I tested all relays and LED.

I will probe the pins tomorrow with the analyser to check the timings are correct (compared to the original firmware of the board) and will be able to proceed with my Modbus master development using this board as a tool for it. After that it will probably get repurposed for some home automation project :)

You will probably polish a few things here and there but for me this is good enough :) Let me know if you need any extra feedback.

TG9541 commented 4 years ago

@tealbrains that's great to hear - thanks for patience and support :-) I'm looking forward to timing test results!

I'll close this issue now and open a new issue for the next steps. On my list are better support for a traditional MODBUS address space, node-id and baud rate init, maybe a blinkenlights for node hit, miss and CRC error, and certainly more docs.

tealbrains commented 4 years ago

@TG9541 Just checked timing. It works! The original firmware would receive commands from my master fine but the reply would be out of whack. Your implementation of modbus works great.

TG9541 commented 4 years ago

@tealbrains thanks!

This reminds me of a test I did before starting this project: https://github.com/TG9541/stm8ef/issues/238#issuecomment-451665398

That issue there contains some points that might be interesting for you :-)