meta data for this page
  •  

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
arduino:code_collection [2025/02/20 23:22] – [Convert float 2 registers] vamsanarduino:code_collection [2025/03/22 22:54] (current) – [Float to char[]] vamsan
Line 1: Line 1:
 ====== LamaPLC: Arduino code collection ====== ====== LamaPLC: Arduino code collection ======
 +===== Frequently used code collection =====
 +==== TON ====
 +<code c>
 +  // var def block
 +  unsigned long startMillis, currentMillis;     // current and start time
 +  const unsigned long period = 2000;            // the value is a number of milliseconds
  
-===== Modbus =====+  // code block 
 +  currentMillis = millis();                     // get the current "time" (actually the number of milliseconds since the program started) 
 +  if (currentMillis - startMillis >= period)    // test whether the period has elapsed 
 +  { 
 +    startMillis = currentMillis;                // time update 
 +    // after time has elapsed the call 
 +    // ... 
 +  }   
 +</code> 
 + 
 +==== check serial monitor ==== 
 +<code c> 
 + 
 +  // code in setup() 
 +  Serial.begin(9600); 
 +   
 +  while (!Serial) { 
 +    ; // wait for serial port to connect. Needed for native USB port only 
 +  } 
 +  Serial.println("Serial monitor OK"); 
 +</code> 
 +===== Converting code collection ===== 
 +==== Float to char[] ==== 
 +<code c> 
 +// lib init (optional) 
 +#include "avr/dtostrf.h" 
 +// converting  
 +float a; 
 +char sendValue[10]; 
 +dtostrf (a, 10, 8, sendValue); // float_value, min_width, num_digits_after_decimal, where_to_store_string 
 + 
 +</code> 
 + 
 +==== Int to char[] ==== 
 +<code c> 
 +int a; 
 +char sendValue[10]; 
 +itoa (i,sendValue,10); // int value, char * str, int base 
 +// base:  Numerical base used to represent the value as a string, between 2 and 36, where 10 means decimal base, 16 hexadecimal, 8 octal, and 2 binary 
 + 
 +</code> 
 +==== String to char[] ==== 
 +<code c> 
 + 
 +char place[20]; 
 +strcpy(place,"Home"); 
 + 
 +</code> 
 +===== Modbus code collection =====
 ==== Convert 2 registers to float ==== ==== Convert 2 registers to float ====
 call: [float] = //modbus_2regs_2_float//([1.register], [2.register]) \\ call: [float] = //modbus_2regs_2_float//([1.register], [2.register]) \\
Line 12: Line 66:
 } }
 </code>  </code> 
 +
 +call: [float] = //modbus_2regs_2_float//([first register]) \\
 +
 +<code c>
 +float modbus_2regs_2_float(uint16_t addr) {
 +    uint16_t a = node.getResponseBuffer(addr);
 +    uint16_t b = node.getResponseBuffer(addr+1);
 +    uint32_t combined = ((uint32_t)a << 16) | b;
 +    float f;
 +    memcpy(&f, &combined, sizeof f);
 +    return f;
 +}
 +</code>
  
 ==== Convert float 2 registers  ==== ==== Convert float 2 registers  ====
Line 28: Line 95:
 </code>  </code> 
 Source: https://docs.ros.org/en/melodic/api/libmodbus/html/modbus-data_8c.html Source: https://docs.ros.org/en/melodic/api/libmodbus/html/modbus-data_8c.html
 +
 +==== Convert 2 registers to int32 ====
 +<code c>
 +uint32_t make_32bit_word(uint16_t hi_word, uint16_t lo_word)
 +{
 +    uint16_t words_16bit[2] = {hi_word, lo_word};
 +    uint32_t word_32bit = 0;
 +
 +    memcpy(&word_32bit, words_16bit, 4);
 +
 +    return word_32bit;
 +}
 +</code>
 +
 +int32 convert direct to float by division by a thousand: \\
 +
 +<code c>
 +float make_float_32bit_word(uint16_t hi_word, uint16_t lo_word)
 +{
 +    uint16_t words_16bit[2] = {hi_word, lo_word};
 +    uint32_t word_32bit = 0;
 +    float back;
 +
 +    memcpy(&word_32bit, words_16bit, 4);
 +    back = word_32bit / 1000.0;
 +    return back;
 +}
 +</code>
 +
 +call: [float] = //make_float_32bit_word//([first reg]) \\
 +
 +<code c>
 +float make_float_32bit_word(uint16_t addr)
 +{
 +    uint16_t words_16bit[2]; 
 +    words_16bit[1] = node.getResponseBuffer(addr);
 +    words_16bit[0] = node.getResponseBuffer(addr+1);
 +    uint32_t word_32bit = 0;
 +    float back;
 +
 +    memcpy(&word_32bit, words_16bit, 4);
 +    back = word_32bit / 1000.0;
 +    return back;
 +}
 +</code>
 ==== Float to / from one register ==== ==== Float to / from one register ====
 <color red>Note: The maximum value of the int16 type is 32767, so in this format only the value range 0 .. 327.67 can be stored with 2 decimal places!</color> <color red>Note: The maximum value of the int16 type is 32767, so in this format only the value range 0 .. 327.67 can be stored with 2 decimal places!</color>
Line 35: Line 147:
 // back one reg to float // back one reg to float
 float Humidity = holdingRegs[REG_HUM] / 100.0; float Humidity = holdingRegs[REG_HUM] / 100.0;
 +</code>
 +
 +==== Modbus #define conversions ====
 +<code c>
 +#define MODBUS_GET_HIGH_BYTE(data) (((data) >> 8) & 0xFF)
 +#define MODBUS_GET_LOW_BYTE(data)  ((data) & 0xFF)
 +#define MODBUS_GET_INT64_FROM_INT16(tab_int16, index)                                  \
 +    (((int64_t) tab_int16[(index)] << 48) | ((int64_t) tab_int16[(index) + 1] << 32) | \
 +     ((int64_t) tab_int16[(index) + 2] << 16) | (int64_t) tab_int16[(index) + 3])
 +#define MODBUS_GET_INT32_FROM_INT16(tab_int16, index) \
 +    (((int32_t) tab_int16[(index)] << 16) | (int32_t) tab_int16[(index) + 1])
 +#define MODBUS_GET_INT16_FROM_INT8(tab_int8, index) \
 +    (((int16_t) tab_int8[(index)] << 8) | (int16_t) tab_int8[(index) + 1])
 +#define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value)            \
 +    do {                                                            \
 +        ((int8_t *) (tab_int8))[(index)] = (int8_t) ((value) >> 8); \
 +        ((int8_t *) (tab_int8))[(index) + 1] = (int8_t) (value);    \
 +    } while (0)
 +#define MODBUS_SET_INT32_TO_INT16(tab_int16, index, value)              \
 +    do {                                                                \
 +        ((int16_t *) (tab_int16))[(index)] = (int16_t) ((value) >> 16); \
 +        ((int16_t *) (tab_int16))[(index) + 1] = (int16_t) (value);     \
 +    } while (0)
 +#define MODBUS_SET_INT64_TO_INT16(tab_int16, index, value)                  \
 +    do {                                                                    \
 +        ((int16_t *) (tab_int16))[(index)] = (int16_t) ((value) >> 48);     \
 +        ((int16_t *) (tab_int16))[(index) + 1] = (int16_t) ((value) >> 32); \
 +        ((int16_t *) (tab_int16))[(index) + 2] = (int16_t) ((value) >> 16); \
 +        ((int16_t *) (tab_int16))[(index) + 3] = (int16_t) (value);         \
 +    } while (0)
 </code> </code>
  
Line 77: Line 219:
   Serial.println(tmpstr2);   Serial.println(tmpstr2);
   return false;   return false;
 +}
 +</code>
 +
 +===== General code collection =====
 +==== MAC random generator ====
 +Generate random MAC using pseudo random generator, bytes 0, 1 and 2 are static (MAC_START), bytes 3, 4 and 5 are generated randomly
 +<code c>
 +void generateMac() {
 +  // Marsaglia algorithm from https://github.com/RobTillaart/randomHelpers
 +  seed1 = 36969L * (seed1 & 65535L) + (seed1 >> 16);
 +  seed2 = 18000L * (seed2 & 65535L) + (seed2 >> 16);
 +  uint32_t randomBuffer = (seed1 << 16) + seed2; /* 32-bit random */
 +  memcpy(data.mac, MAC_START, 3);                // set first 3 bytes
 +  for (byte i = 0; i < 3; i++) {
 +    data.mac[i + 3] = randomBuffer & 0xFF;  // random last 3 bytes
 +    randomBuffer >>= 8;
 +  }
 } }
 </code> </code>