Electronza
  • Homepage
  • Privacy
    • Privacy Policy
  • Contact
Electronza
  • Homepage
  • Privacy
    • Privacy Policy
  • Contact
Electronza
You are at:Home»Electronics projects»Arduino projects»4-20mA T current loop Arduino tutorial Part II: transmitter
Arduino Uno 4-20mA communication using 4-20mA R click and 4-20mA T click boards from MikroElektronika: MIKROE-1296, MIKROE-1387, Uno Click Shield
4-20mA Transmitter and Receiver Click Boards

4-20mA T current loop Arduino tutorial Part II: transmitter

6
By Electronza on August 19, 2016 Arduino projects, Tutorials

In my previous post I wrote a bit of the hardware aspects of using a pair of 4-20mA R and 4-20mA T  click boards from MikroElektronika in an Arduino environment. Today I will make a further progress in this tutorial and I will describe how to implement the transmitter side, using a pair of 4-20mA receiver and transmitter click boards, Arduino Uno boards and Arduino Uno click shields.

As the transmitter implements galvanic separation, I can’t power the transmitter from the loop itself. This is a bit different from what you’ll find in industrial environments, where the transmitter can be energized either by by the current loop itself, or by using some 3-wire or 4-wire setups. You can read more about these topologies in this guide from Libelium.

Anyway, in my setup I must provide separate power sources for the transmitter and the receiver. Furthermore, as the loop side of the transmitter is powered from the loop, the receiver must be on for the transmitter to work.

4-20mA Transmitter and Receiver with Arduino Uno
4-20mA Transmitter and Receiver with Arduino Uno

So, I used two Arduino Uno boards, two Arduino Uno Click shields, one 4-20mA T click and one 4-20mA R click. Each Arduino Uno is powered from its own supply. Both 4-20mA click boards were reconfigured for 5V operation by moving the SMD jumpers into the 5V position.

With the current loop powered the next step to perform is calibration of the transmitter. That is, I have to know what to write to the DAC registers to set the current through the loop to 20mA and what to write in order to set the current to 4mA.

The calibration routine I propose looks like this:

/*
  4-20mA T click calibration
 */
#include <SPI.h>

// Arduino UNO with Mikroe Arduino Uno Click shield
// 4-20mA is placed in socket #2
// CS   is pin 9
// SCK  is pin 13
// MISO is pin 12
// MOSI is pin 11
#define DAC_CS 9

// Used to receive data from serial port
int received;

void setup() {
  // initialize serial
  Serial.begin(9600);
  // initialize SPI
  SPI.begin();
  pinMode(DAC_CS, OUTPUT);
}

void loop() {
  // if there's any serial available, read it:
  while (Serial.available() > 0) {
    // look for the next valid integer in the incoming serial stream:
    int received = Serial.parseInt();
    // look for the newline. That's the end of your
    // sentence:
    if (Serial.read() == '\n') {
      // constrain the values to 0 - 255 and invert
      // if you're using a common-cathode LED, just use "constrain(color, 0, 255);"
      received = constrain(received, 0, 4095);

      Serial.print("DAC is set to value : ");
      Serial.println(received);

      // now send it to the DAC
      set_DAC(received);
    }
  }
}


/*******************************************************************************
* Function set_DAC(int set_value)
* ******************************************************************************

DAC works on SPI
We must send 16 bits
byte1 is [WR, BUF, /GA, /SHDN, data11, data10, data9, data8]
byte2 is [data7, data6, data5, data4, data3, data2, data1, data0]
Write code
WR    0 - write to DAC register
      1 - Ignore this command
VREF Input Buffer Control bit
BUF   0 - Unbuffered
      1 - Buffered
Output Gain Selection bit
/GA   0 - 1x (VOUT = VREF * D/4096)
      1 - 0 = 2x (VOUT = 2 * VREF * D/4096)
Output Shutdown Control bit
/SHDN 0 - Shutdown the device. Analog output is not available.
      1 - Active mode operation. VOUT is available

WR has to be 0 to write to DAC registers
BUF is set to 0 (unbuffered)
GAIN MUST BE SET TO 1. We can't output more than the Vcc!!!
SHDN also set to 1 to have DAC active.
00110000 = 0x30
*/

void set_DAC(int set_value){
  byte first_byte;
  byte second_byte;

  first_byte = (set_value >> 8) & 0x0F;
  first_byte = first_byte | 0x30;
  second_byte = set_value & 0xFF;

  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  digitalWrite(DAC_CS, 0);
  SPI.transfer(first_byte);
  SPI.transfer(second_byte);
  digitalWrite(DAC_CS, 1);
  SPI.endTransaction();
}

To calibrate the transmitter I used the serial monitor to send values to the DAC. Valid values are from 0 to 4095. Anything outside this range will be mapped to one of the extremes.

The values sent through the serial monitor are written to the DAC registers, and as result the current through the loop changes. An miliammeter is used to measure this current, and I recorded the DAC_4mA and the DAC_20mA values. Those values are then used in the transmitter routine.

In my tutorial, for a length of about 15m of (good quality) UTP cable to get 4mA through the loop I recorded DAC_40mA = 801 and to get 20mA I’ve got DAC_20mA = 3994.

4-20mA T Arduino IDE code for the transmitter

With the above values I can write the transmitter code. The code in this tutorial reads the value on the A0 pin, maps the result to the [DAC_4mA,…, DAC_20mA] range and updates the DAC registers accordingly:

/*
  4-20mA T click transmitter code

  This code reads the voltage on pin A0
  and sends the result on 4-20mA current loop

 */

#include <SPI.h>

// Arduino UNO with Mikroe Arduino Uno Click shield
// 4-20mA is placed in socket #2
// CS   is pin 9
// SCK  is pin 13
// MISO is pin 12
// MOSI is pin 11
#define DAC_CS 9

// Calibration data obtained by running the calibration code
const int DAC_4mA  = 796;
const int DAC_20mA = 3982;

// Data min and max range
const int data_min_range = 0;
const int data_max_range = 1023;


// Read from A0 pin
int analog_value;

// Debug mode? (1 - debug, 0 - no debug);
bool debug_mode = 1;

void setup() {

  // Are we in debug mode
  if (debug_mode == 1){
     // Initialize serial
     Serial.begin(9600);
  }

  // Initialize SPI
  pinMode(DAC_CS, OUTPUT);
  digitalWrite(DAC_CS, 1);
  SPI.begin();

}

void loop() {

  // Read the input on analog pin 0:
  analog_value = analogRead(A0);

  // Transmit data
  SendTo420mA(analog_value);

  // Are we in debug mode
  if (debug_mode == 1){
     // Print information
     Serial.print("Transmitted value is: ");
     Serial.println(analog_value);
  }
  
  // Don't update too often, it doesn't make sense
  delay(500);

}

void set_DAC(int set_value){
/*
DAC works on SPI
We must send 16 bits
byte1 is [WR, BUF, /GA, /SHDN, data11, data10, data9, data8]
byte2 is [data7, data6, data5, data4, data3, data2, data1, data0]
Write code
WR    0 - write to DAC register
      1 - Ignore this command
VREF Input Buffer Control bit
BUF   0 - Unbuffered
      1 - Buffered
Output Gain Selection bit
/GA   0 - 1x (VOUT = VREF * D/4096)
      1 - 0 = 2x (VOUT = 2 * VREF * D/4096)
Output Shutdown Control bit
/SHDN 0 - Shutdown the device. Analog output is not available.
      1 - Active mode operation. VOUT is available

WR has to be 0 to write to DAC registers
BUF is set to 0 (unbuffered)
GAIN MUST BE SET TO 1. We can't output more than the Vcc!!!
SHDN also set to 1 to have DAC active.
00110000 = 0x30
*/

  byte first_byte;
  byte second_byte;

  first_byte = (set_value >> 8) & 0x0F;
  first_byte = first_byte | 0x30;
  second_byte = set_value & 0xFF;

  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  digitalWrite(DAC_CS, 0);
  SPI.transfer(first_byte);
  SPI.transfer(second_byte);
  digitalWrite(DAC_CS, 1);
  SPI.endTransaction();

  // Are we in debug mode
  if (debug_mode == 1){
    // Print information
    Serial.print("DAC is set to: ");
    Serial.println(set_value);
    Serial.println();
  }
}

void SendTo420mA(unsigned int transmitted_Value)
{
  // Map the data to be sent into DAC values
  // that result in a loop current between 4 and 20mA
  int temp = map(transmitted_Value, data_min_range, data_max_range, DAC_4mA, DAC_20mA);
  // update the current loop
  set_DAC(temp);
}

Have you missed the previous post?

4-20mA current loop Arduino tutorial Part I: hardware

Further reading

4-20mA R current loop Arduino tutorial Part III: Receiver

[]
4-20mA 4-20mA T click 4-20mA R click MIKROE-1296 MIKROE-1387 Arduino Uno Click Shield
Share. Facebook Twitter Pinterest LinkedIn Tumblr Email

Related Posts

Some software services that make my life easier

SPEC Digital H2S sensor

SPEC DGS sensors: new firmware, new behaviour

SDS011 - HPMA115S0 - Arduino Due

A comparative test of two particle sensors

6 Comments

  1. Tom Smith on May 11, 2018 11:08 am

    Hi , Brilliant tutorial. Trying to get your program to work but I get no output on the serial monitor when calibrating and subsequently no current output.

    I have no idea why it isn’t working as I have used the same program and was wondering if you could shed any light on the subject.

    Best regards

    Tom

    Reply
    • Teodor Costachioiu on May 11, 2018 11:12 am

      Hi

      Does the serial output work when you run one of the Arduino IDE examples? Also, please note that in my code example the 4-20mA click board is placed in socket #2, which uses pin 9 for CS. You have to change the code line #define DAC_CS 9 if you are using another pin as CS.

      Reply
  2. Jenisha Noble on December 7, 2018 11:15 am

    Hi, Thanks a lot for your tutorial. Its very helpful but i am trying it and it doesnt work. I have a few doubts which I hope you can help me with.
    1. I am not using a 15m length UTP cable but maybe 15cm twisted pair cable, Should I check the resistance between thís cable to determine the current flow.
    2. I dont have a milliammeter but multimeter and so could you please guide as how to calibrate the values for DAC_4mA and DAC_20mA.

    I look foward to your reply. Thanks in advance.

    Reply
    • Teodor Costachioiu on December 7, 2018 11:21 am

      Hi.

      Any multimeter that has 0-200mA range will do. Just put it in series with the cable.
      The cable length (and its resistance) should become important at longer distances (think over 50-100m, depending on the quality of the cable).
      Also, bear in mind that the 4-20mA R receiver needs its own power supply, it cannot be powered from the 4-20mA bus.

      Hope this helps,
      Teodor

      Reply
  3. Jenisha Noble on December 7, 2018 12:15 pm

    Hi, thanks for your reply. I tried it but i think it doesnt work. I get the below values in my com port when i execute the transmitter module.
    1123Transmitted value is: 418
    DAC is set to: 1080

    1080Transmitted value is: 397
    DAC is set to: 895

    895Transmitted value is: 307
    DAC is set to: 1156

    1156Transmitted value is: 434
    DAC is set to: 1223

    1223Transmitted value is: 467
    DAC is set to: 1045

    1045Transmitted value is: 380
    DAC is set to: 897

    897Transmitted value is: 308
    DAC is set to: 1041

    1041Transmitted value hs: 378
    DAC is set to: 1190

    1190Transmitted value is: 451
    DC is set to: 1170

    1170Transmitted value is: 441
    DAC is set to: 979

    979Transmitted value is: 348
    DAC is set to: 903

    903Transmitted value is: 311
    DAB is set to: 1168

    1168Transmitted value is: 440
    DAC is set to: 1184

    1184Transmitted value is: 448
    DAC is set to: 994

    994Transmitted value is: 355
    DAC is set to: 877

    Could you please suggest how to proceed further or let me know how the result should look like to have a better idea.

    Thanks and Regards,
    Jenisha Noble

    Reply
    • Teodor Costachioiu on December 12, 2018 11:03 am

      The calibration of the 4-20mA transmitter and receiver click boards is a two-step project.

      The receiver provides power to the bus, the transmitter controls the current through the bus, by writing various values into the A/D converter that drives the ADuM1411.

      STEP1: TRANSMITTER CALIBRATION

      The first step is to determine (empirically) the DAC_4mA value that corresponds to a 4mA current through the bus, and the DAC_20mA value that corresponds to 20mA through the bus. Those values are influenced by a lot of factors, such as the cable resistance (which in its turn depends on the cable length and cable type).

      You do this by putting a milliammeter in series with the bus, and by measuring the current. Any multimeter that has a 0-200mA range will do. The overall precision of the whole project depends on this calibration. However, in practice, most student/maker projects won’t need a very high precision anyway.

      Then, you write different values into the DAC of the transmitter board, until you get a 4mA reading of the current. That is the DAC_4mA value.
      Repeat the process to get a 20mA current through the bus, and determine the DAC_20mA value.

      Please observe that, depending on which value you write into the DAC, you can have current readings over the bus that are below 4mA or over 20mA.
      The thing to remember is that one can use the 4mA and 20mA limits to perform fault detection:
      – anything lower than 4mA might indicate an open bus (broken wires, etc.)
      – anything higher than 20mA might indicate a short circuit over the bus.

      STEP2. RECEIVER CALIBRATION

      The receiver performs two functions: it provides power to the bus (about 16V), and it measures the current through the bus. The power supply is an SMPS implemented with a TPS61041.
      The current measuring is implemented with one INA196 current shunt monitors with voltage output. Its output voltage is applied to an MCP3201 ADC.

      Here we go to the second step of the calibration: you need to determine the ADC_4mA value which corresponds to a 4mA current over the bus, and the ADC_20mA value which corresponds to a 20mA current over the bus.

      You do this by configuring the transmitter to send 4mA over the bus by writing the DAC_4mA value in its MCP4921 DAC. Now you have 4mA over the bus, and you can use the receiver calibration code to read the ADC_4mA value.
      Do the same for 20mA, to get the ADC_20mA value.

      Finally, you can use those values to perform remapping of the data, like in those line of code:
      – in the transmitter
      temp = map(transmitted_Value, data_min_range, data_max_range, DAC_4mA, DAC_20mA);
      – in the receiver
      The calibration of the 4-20mA transmitter and receiver click boards is a two-step project.

      The receiver provides power to the bus, the transmitter controls the current through the bus, by writing various values into the A/D converter that drives the ADuM1411.

      STEP1: TRANSMITTER CALIBRATION

      The first step is to determine (empirically) the DAC_4mA value that corresponds to a 4mA current through the bus, and the DAC_20mA value that corresponds to 20mA through the bus. Those values are influenced by a lot of factors, such as the cable resistance (which in its turn depends on the cable length and cable type).

      You do this by putting a milliammeter in series with the bus, and by measuring the current. Any multimeter that has a 0-200mA range will do. The overall precision of the whole project depends on this calibration. However, in practice, most student/maker projects won’t need a very high precision anyway.

      Then, you write different values into the DAC of the transmitter board, until you get a 4mA reading of the current. That is the DAC_4mA value.
      Repeat the process to get a 20mA current through the bus, and determine the DAC_20mA value.

      Please observe that, depending on which value you write into the DAC, you can have current readings over the bus that are below 4mA or over 20mA.
      The thing to remember is that one can use the 4mA and 20mA limits to perform fault detection:
      – anything lower than 4mA might indicate an open bus (broken wires, etc.)
      – anything higher than 20mA might indicate a short circuit over the bus.

      STEP2. RECEIVER CALIBRATION

      The receiver performs two functions: it provides power to the bus (about 16V), and it measures the current through the bus. The power supply is an SMPS implemented with a TPS61041.
      The current measuring is implemented with one INA196 current shunt monitors with voltage output. Its output voltage is applied to an MCP3201 ADC.

      Here we go to the second step of the calibration: you need to determine the ADC_4mA value which corresponds to a 4mA current over the bus, and the ADC_20mA value which corresponds to a 20mA current over the bus.

      You do this by configuring the transmitter to send 4mA over the bus by writing the DAC_4mA value in its MCP4921 DAC. Now you have 4mA over the bus, and you can use the receiver calibration code to read the ADC_4mA value.
      Do the same for 20mA, to get the ADC_20mA value.

      Finally, you can use those values to perform remapping of the data, like in those line of code:
      – in the transmitter
      temp = map(transmitted_Value, data_min_range, data_max_range, DAC_4mA, DAC_20mA);
      – in the receiver
      received_data = map(loop_current, ADC_4mA, ADC_20mA, data_min_range, data_max_range);

      Reply

Leave A Reply Cancel Reply

Latest posts
January 15, 2023

A pretty text box for Blogger posts

January 15, 2023

New blog section: beginners’ corner

January 15, 2023

Cleaning unused images from blogs hosted on Blogger

Categories
  • Beginners' corner
  • Electronics projects
    • ESP8266
    • Arduino projects
    • IoT
    • 8-bit PIC projects
    • Raspberry PI
    • PIC32 projects
    • Robots
  • Arduino libraries
  • Reviews
    • Tools & equipment
    • Development boards
    • IoT
    • Industrial Arduino
  • Blogger / Blogspot
  • Tutorials
  • Casual stuff
Popular posts
Arduino Uno 4-20mA communication using 4-20mA R click and 4-20mA T click boards from MikroElektronika: MIKROE-1296, MIKROE-1387, Uno Click Shield
August 17, 2016

4-20mA current loop Arduino tutorial Part I: hardware

ECG click on Arduino Uno
December 5, 2016

ECG click: Arduino IDE code examples

Arduino water timer
February 25, 2015

Gardena water timer controller using Arduino Uno

ESP8266 Thing Dev from Sparkfun
May 15, 2019

ESP8266 – running on battery power

Thunderstorm
February 10, 2015

AS3935 lightning detection using Arduino Uno

Copyright © 2023 Teodor Costachioiu

Type above and press Enter to search. Press Esc to cancel.