Modbus Master and Slave on STM32F103 and UNO

Generic boards that are not Maple or Maple mini clones, and don't contain the additional USB reset hardware
messaf
Posts: 7
Joined: Wed Jan 18, 2017 10:55 am

Modbus Master and Slave on STM32F103 and UNO

Postby messaf » Wed Jan 18, 2017 11:29 am

Good day!
I have a problem:
I use Arduino Ide and fees on STM32F103C8T6, you must establish a connection via the RS-485 between the Master (STM32F103) and slave (Arduino Uno). Use the library SimpleModbus NG (https://github.com/angeloc/simplemodbusng). Sketches are compiled without problems. To use an example from STM32F103 library (SimpleModbusMasterExample.ino) and use UART1 - Serial1 (PA9-TX1, PA10-PX1 and control of transmit / receive pin PA8 for the MAX485). For example UNO used SimpleModbusSlaveExample.ino and Serial (default TX, PX and pin 2 - transmit / receive control).
So, the problem is that the UNO does not respond to requests STM32. Master returns a timeout error. But the fact is that if the master flash sketch in Arduino Mega 2560 is a problem in the communication between master and slave is not there, everything works, and the data is transmitted, and even tried to slave (UNO) to connect to a PC using an app for Windows "Modbus Master"- problems with this too does not arise.
Please answer, what could be the problem?

stevestrong
Posts: 722
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Modbus Master and Slave on STM32F103 and UNO

Postby stevestrong » Wed Jan 18, 2017 12:41 pm

Try to connect serial 1 of F103 with the PC over RS485, see if the PC receives data when F103 is master and PC is slave.

You could post here your sketch.

tyro
Posts: 10
Joined: Thu Jan 19, 2017 3:44 pm

Re: Modbus Master and Slave on STM32F103 and UNO

Postby tyro » Thu Jan 19, 2017 3:52 pm

I am using different library for Modbus Master functionality. Author is Doc Walker. It fully works and was tested using Arduino Uno, Arduino Mega, Arduino Nano. But when I compiled this code to use with Blue Pill Or Maple Mini device do not get answers from devices. Maybe it do not call proper calls too. Before compiiling I had problem with CRC functionality. Function "word" and data type "word" is not compatible with STM32F103, so I updated using examples how to change word to different types found on forums. I think there may be problem errors comes from.

So, I would be really interested to find solution to make Maple Mini work as Modbus Master. Otherwise I will have to add something like Attiny85 between Modbus slave device and Maple mini to play role of translator.
Last edited by tyro on Fri Jan 20, 2017 7:12 am, edited 1 time in total.

stevestrong
Posts: 722
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Modbus Master and Slave on STM32F103 and UNO

Postby stevestrong » Thu Jan 19, 2017 7:47 pm

I have 2 blue pills communicating with each other over RS485 without any special lib. It is just using the normal serial communication and one control signal for direction.
The possible problem you can have is that the oroginal RS485 adapters use chips that are working with 4.5V and above. So it will most probably not work with 3.3V from the F103 board. I solved the problem by replacing the onboard RS485 chip with the 3.3V working ADM3485.

messaf
Posts: 7
Joined: Wed Jan 18, 2017 10:55 am

Re: Modbus Master and Slave on STM32F103 and UNO

Postby messaf » Mon Jan 23, 2017 2:50 am

Hello guys. Thanks for answers! Am sorry for not having replied.
I've already figured out in his problemme, it appears in the source code of the library Modbus Master function of sending the package: void sendPacket (unsigned char bufferSize). So pay attention to this code:

Code: Select all

void sendPacket(unsigned char bufferSize)
{
   digitalWrite(TxEnablePin, HIGH);
      
   for (unsigned char i = 0; i < bufferSize; i++)
      Serial2.write(frame[i]);
   
   
       Serial2.flush();

   
   // allow a frame delay to indicate end of transmission
   delayMicroseconds(T3_5);
   
   digitalWrite(TxEnablePin, LOW);

      
   previousTimeout = millis(); // initialize timeout delay   
}


This code works correctly for Arduino boards, ie the function Serial2.flush () provides flow control and buffer underrun.
For STM32F103 this option is not necessary - this function simply clears the send buffer without waiting for the data in its entirety. The decision as follows:

Code: Select all

void sendPacket(unsigned char bufferSize)
{
   digitalWrite(TxEnablePin, HIGH);
      
   for (unsigned char i = 0; i < bufferSize; i++)
      Serial2.write(frame[i]);
   
     //   Serial2.flush();  //Commenting - this is only for Arduino
     //  Change for STM32F103 on:
    usart_reg_map *regs = USART2->regs;
    while ( !(regs->SR & USART_SR_TC) ); // Wait for Transmission Complete to set

   // allow a frame delay to indicate end of transmission
   delayMicroseconds(T3_5);
   
   digitalWrite(TxEnablePin, LOW);

      
   previousTimeout = millis(); // initialize timeout delay   
}

The solution was found in this thread (RS485 - Waiting for transmit to finish)

As for your posts:
tyro wrote:Before compiiling I had problem with CRC functionality. Function "word" and data type "word" is not compatible with STM32F103, so I updated using examples how to change word to different types found on forums. I think there may be problem errors comes from.


Could you share the code with the problem "word" and data type "word" ?

tyro
Posts: 10
Joined: Thu Jan 19, 2017 3:44 pm

Re: Modbus Master and Slave on STM32F103 and UNO

Postby tyro » Mon Jan 23, 2017 9:28 pm

messaf wrote:Could you share the code with the problem "word" and data type "word" ?


As i have said I use ModbusMaster. I like it as i need many different requests and i discovered it is very easy to change address and registers number on every request. Problems I have with this library and "word" - they were treated as "expression list treated as compound expression in functional cast". I have fixed them as found on forum - changed word to conversion of bytes. Fixing this i have changed:
Line

Code: Select all

_u16ResponseBuffer[i] = word(u8ModbusADU[2 * i + 4], u8ModbusADU[2 * i + 3]);

was changed to

Code: Select all

_u16ResponseBuffer[i] = (u8ModbusADU[2 * i + 4] << 8) | u8ModbusADU[2 * i + 3];


and line

Code: Select all

_u16ResponseBuffer[i] = word(0, u8ModbusADU[2 * i + 3]);

changed with

Code: Select all

_u16ResponseBuffer[i] = 0 << 8 | u8ModbusADU[2 * i + 3];


and lastly

Code: Select all

_u16ResponseBuffer[i] = word(u8ModbusADU[2 * i + 3], u8ModbusADU[2 * i + 4]);

to

Code: Select all

_u16ResponseBuffer[i] = (u8ModbusADU[2 * i + 3] << 8) | u8ModbusADU[2 * i + 4];


After these changes it compiles for Arduino Nano and works as espected.

And other error for maple Mini ir BluePill is that compiler says function "send()" is ambiguous: "call of overloaded 'send(word)' is ambiguous".
We here have several declarations of send() functions with different data types:
  • void send(uint8_t)
  • void send(uint16_t)
  • void send(uint32_t)

When I comment first one (with type uint8_t) it compiles. But do not work as expected (no responses). What type of these may removed or changed to other code to compile code properly for STM32duino devices?

stevestrong
Posts: 722
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Modbus Master and Slave on STM32F103 and UNO

Postby stevestrong » Mon Jan 23, 2017 10:26 pm

Regarding overloaded "send()".
I suppose you know how many bytes or words do you want to send.
So just cast the passed parameters/constants like:

Code: Select all

send( (uint8_t)0x5a );

or

Code: Select all

send( (uint16_t)0x5a );

and it should work as expected.

tyro
Posts: 10
Joined: Thu Jan 19, 2017 3:44 pm

Re: Modbus Master and Slave on STM32F103 and UNO

Postby tyro » Tue Jan 24, 2017 9:06 am

As I returned to this library code I saw that there is type "word" inside. And this function uses one more too:

Code: Select all

void ModbusMaster::send(uint8_t data)
{
  send(word(data));
}


I found how to convert word with two numbers to usual format, but don't know that will work with single param.

Info about word for others interested:
There are a few ways you can do this:

1) unsigned int word = high_byte * 256 + low_byte;

2) unsigned int word = ((unsigned int)high_byte << 8) + low_byte

As I've used second one, but on different forum it was written a bit different, so I'll have to check it works corectly or update.

As one more of resources for others try http://forum.arduino.cc/index.php?topic=263668.msg1860255#msg1860255.

I found that word is just insigned int 16bit long. So maybe that will work - updated code compiles correctly:

Code: Select all

send((uint16_t) data );


Testing with Modbus protocol for me will be possible only on evening. Will write with results.

User avatar
RogerClark
Posts: 5461
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Modbus Master and Slave on STM32F103 and UNO

Postby RogerClark » Tue Jan 24, 2017 10:16 am

Its generally not advisable to use types like "word" if you need cross platform compatibility, as the meaning seems to vary depending on the processor architecture / data width.

better to use uint16_t etc

tyro
Posts: 10
Joined: Thu Jan 19, 2017 3:44 pm

Re: Modbus Master and Slave on STM32F103 and UNO

Postby tyro » Tue Jan 24, 2017 10:33 am

RogerClark wrote:Its generally not advisable to use types like "word" if you need cross platform compatibility, as the meaning seems to vary depending on the processor architecture / data width.


Yes, I have discovered that now too. So am updating library I am using to work for me :)


Return to “Generic STM32F103”

Who is online

Users browsing this forum: No registered users and 3 guests