GithubHelp home page GithubHelp logo

philippedc / arduino-esp8266-rs485-modbus-anemometer Goto Github PK

View Code? Open in Web Editor NEW
14.0 14.0 8.0 1.02 MB

Here is a way to setup an anemometer that works with RS485 MODBUS communication protocol

License: GNU General Public License v3.0

C++ 100.00%

arduino-esp8266-rs485-modbus-anemometer's People

Contributors

philippedc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

arduino-esp8266-rs485-modbus-anemometer's Issues

ESP8266 with DS3231

Hi Philippe, what needs to be changed in the code for ESP8266 v3.5 so that a DS3231 can be used instead of the DS1307?

Also: there seem to be compiling issues near line 223: i and imax should not be defined as byte at the start?

CRC-16/MODBUS checksum calculation

Philip

Here's another issue I've been working on:
I see that you're testing the 2nd byte in Anenometer_buff[] for RS485 trasmission errors:

while( Anemometer_buf[1] != 0x03 ) { // if received message has an error

I found that wasn't sufficient to trap all the errors.
I've implemented code to do a full CRC-16/MODBUS checksum calculation.
I found reference to it on stackoverflow.com and slightly modified it for C++ (Arduino/ESP8266 IDE) data types. The linked article refers to two methods of calculation. The bytewise version is much faster and that's the one I used. It uses 512 bytes of ROM which shouldn't be a problem on the ESP8266.
I've attached the code I'm using. It works very reliably for me. Perhaps you might want to incorporate it into your code.

Here's the function, CRC16, that calculates the checksum:

    // CRC-16/MODBUS calc function

    uint16_t CRC16 (const byte *nData, uint16_t wLength)
        {
        static const uint16_t wCRCTable[] = {
        0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
        0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
        0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
        0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
        0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
        0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
        0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
        0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
        0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
        0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
        0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
        0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
        0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
        0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
        0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
        0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
        0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
        0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
        0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
        0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
        0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
        0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
        0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
        0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
        0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
        0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
        0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
        0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
        0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
        0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
        0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
        0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 };

        byte nTemp;
        uint16_t wCRCWord = 0xFFFF;

        while (wLength--)
            {
            nTemp = *nData++ ^ wCRCWord;
            wCRCWord >>= 8;
            wCRCWord  ^= wCRCTable[(nTemp & 0xFF)];
            }
        return wCRCWord;
        } // End: CRC16

And here's the code that calls the CRC16 function. It passes the first 5 bytes from responseFrameBuff[] to the CRC16 function, which returns the 2 byte CRC. This is tested against the CRC in responseFrameBuff[] (last 2 bytes). The code will loop until an Inquiry returns data with a valid checksum. (In my code the receive buffer is called responseFrameBuff[] rather than Anenometer_buff[] because I use it for both Anenometer and Wind Direction sensors):

#define rtsPin D5                              // RS485 RTS direction control
#define transmit HIGH
#define receive LOW

byte responseFrameBuff[7] = {};                // buffer for receiving response frame from sensors

const byte anemometerInquiryFrame[] = {0x03, 0x03, 0x00, 0x00, 0x00, 0x01, 0x85, 0xE8};            // Wind Speed Sensor Inquiry frame
const byte windDirectionInquiryFrame[] = {0x02, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x39};         // Wind Direction Sensor Inquiry frame


        word checksum;
        word crc;
        do
            {
            digitalWrite(rtsPin, transmit);                                        // init transmission
            RS485.write(anemometerInquiryFrame, sizeof(anemometerInquiryFrame));   // send the Inquiry
            RS485.flush();                                                         // Wait for the transmission to complete

            digitalWrite(rtsPin, receive);                                         // init receive
            RS485.readBytes(responseFrameBuff, 7);                                 // read the data

            checksum = CRC16 (responseFrameBuff, 5);                               // calculate CRC-16/MODBUS checksum
            crc = responseFrameBuff[6] * 256 + responseFrameBuff[5];               // get checksum from buffer
            }
        while (checksum != crc);                                                   // test if checksum is ok

allocating and reading 8 bytes to `Anemometer_buff[]`

Why are you allocating and reading 8 bytes to Anemometer_buff[]? The Response Frame only has 7 bytes.
Reading 8 bytes limits the response time to > 1 second, perhaps hitting the Serial.setTimeout() default of 1 second on the 8th byte.
Your test output to the serial monitor is reading 7 bytes.
You can check the return value of RS485Serial.readBytes(anemometerBuff, 8) which will return the number of bytes placed in the buffer (7).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.