Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <avr/wdt.h>
- #include <Wire.h>
- //#include <LiquidCrystal_I2C.h>
- #include <Adafruit_ADS1015.h>
- #include <SimpleModbusSlave.h>
- /* This example code has 9 holding registers. 6 analogue inputs, 1 button, 1 digital output
- and 1 register to indicate errors encountered since started.
- Function 5 (write single coil) is not implemented so I'm using a whole register
- and function 16 to set the onboard Led on the Atmega328P.
- The modbus_update() method updates the holdingRegs register array and checks communication.
- Note:
- The Arduino serial ring buffer is 128 bytes or 64 registers.
- Most of the time you will connect the arduino to a master via serial
- using a MAX485 or similar.
- In a function 3 request the master will attempt to read from your
- slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
- and two BYTES CRC the master can only request 122 bytes or 61 registers.
- In a function 16 request the master will attempt to write to your
- slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS,
- NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
- 118 bytes or 59 registers.
- Using the FTDI USB to Serial converter the maximum bytes you can send is limited
- to its internal buffer which is 60 bytes or 30 unsigned int registers.
- Thus:
- In a function 3 request the master will attempt to read from your
- slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES
- and two BYTES CRC the master can only request 54 bytes or 27 registers.
- In a function 16 request the master will attempt to write to your
- slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS,
- NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write
- 50 bytes or 25 registers.
- Since it is assumed that you will mostly use the Arduino to connect to a
- master without using a USB to Serial converter the internal buffer is set
- the same as the Arduino Serial ring buffer which is 128 bytes.
- */
- // Using the enum instruction allows for an easy method for adding and
- // removing registers. Doing it this way saves you #defining the size
- // of your slaves register array each time you want to add more registers
- // and at a glimpse informs you of your slaves register layout.
- //////////////// registers of your slave ///////////////////
- enum
- {
- // just add or remove registers and your good to go...
- // The first register starts at address 0
- ADC0,
- ADC1,
- ADC2,
- ADC3,
- ADC4,
- ADC5,
- ADC6,
- ADC7,
- ADC8,
- ADC9,
- ADC10,
- ADC11,
- TOTAL_ERRORS,
- // leave this one
- TOTAL_REGS_SIZE
- // total number of registers for function 3 and 16 share the same register array
- };
- unsigned int holdingRegs[TOTAL_REGS_SIZE]; // function 3 and 16 register array
- ////////////////////////////////////////////////////////////
- //LiquidCrystal_I2C lcd(20, 4);
- Adafruit_ADS1115 ads; /* Use this for the 16-bit version */
- int16_t adc0, adc1, adc2, adc3;
- float v1, v2, v3, v4;
- //String line1, line2, line3, line4;
- union Pun {
- float f; uint32_t u;
- };
- void setup()
- {
- //pinMode(A0, OUTPUT);
- wdt_enable(WDTO_8S);
- //digitalWrite(A0, HIGH);
- //delay(2000);
- //digitalWrite(A0, LOW);
- //lcd.autoAddress();
- //lcd.begin();
- /* parameters(long baudrate,
- unsigned char ID,
- unsigned char transmit enable pin,
- unsigned int holding registers size,
- unsigned char low latency)
- The transmit enable pin is used in half duplex communication to activate a MAX485 or similar
- to deactivate this mode use any value < 2 because 0 & 1 is reserved for Rx & Tx.
- Low latency delays makes the implementation non-standard
- but practically it works with all major modbus master implementations.
- */
- ads.setGain(GAIN_TWOTHIRDS);
- ads.begin();
- modbus_configure(9600, 1, 16, TOTAL_REGS_SIZE, 0);
- }
- void loop()
- {
- // modbus_update() is the only method used in loop(). It returns the total error
- // count since the slave started. You don't have to use it but it's useful
- // for fault finding by the modbus master.
- wdt_reset();
- holdingRegs[TOTAL_ERRORS] = modbus_update(holdingRegs);
- for ( int i = 0; i<4; i++){
- holdingRegs[i] = ads.readADC_SingleEnded(i);
- delayMicroseconds(50);
- }
- v1 = (holdingRegs[0] * 0.1875)/1000;
- v2 = (holdingRegs[1] * 0.1875)/1000;
- v3 = (holdingRegs[2] * 0.1875)/1000;
- v4 = (holdingRegs[3] * 0.1875)/1000;
- encodeFloat(&holdingRegs[4], v1);
- delayMicroseconds(50);
- encodeFloat(&holdingRegs[6], v2);
- delayMicroseconds(50);
- encodeFloat(&holdingRegs[8], v3);
- delayMicroseconds(50);
- encodeFloat(&holdingRegs[10], v4);
- delayMicroseconds(50);
- //unsigned long teg = (unsigned long)holdingRegs[4] << 16 | holdingRegs[5];
- /*
- float dtTeg1 = decodeFloat(&holdingRegs[4]);
- float dtTeg2 = decodeFloat(&holdingRegs[6]);
- float dtTeg3 = decodeFloat(&holdingRegs[8]);
- float dtTeg4 = decodeFloat(&holdingRegs[10]);
- line1 = String(holdingRegs[0]) + ", " + String(dtTeg1,5);
- line2 = String(holdingRegs[1]) + ", " + String(dtTeg2,5);
- line3 = String(holdingRegs[2]) + ", " + String(dtTeg3,5);
- line4 = String(holdingRegs[3]) + ", " + String(dtTeg4,5);
- lcd.clear();
- lcd.setCursor(0,0);
- lcd.print(line1);
- lcd.setCursor(0,1);
- lcd.print(line2);
- lcd.setCursor(0,2);
- lcd.print(line3);
- lcd.setCursor(0,3);
- lcd.print(line4);
- delay(10);
- */
- }
- void encodeFloat(uint16_t *regs, float x){
- union Pun pun;
- pun.f = x;
- regs[0] = (pun.u>>16) & 0xFFFFU;
- regs[1] = pun.u & 0xFFFFU;
- }
- /*float decodeFloat(const uint16_t *regs){
- union Pun pun;
- pun.u = ((uint32_t)regs[0] << 16) | regs[1];
- return pun.f;
- }
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement