text:
Constructing my own serial command syntax to control arduino
I know this is a basic question, but as a hardware electronics guy and not a programmer I cannot seem to fathom how to do this - so any examples of code would be greatly appreciated:
I want the arduino to spit out some initialization chatter on startup - (ok, done easy).
Then I want it to listen for serial commands, they can all be same length if that helps but I want them to be strings. i.e. identifier followed by value
Command --- Result
PWR_TRUE --- Power on device
PWR_FLSE --- Power off device
REP_FREQ --- Print frequency over serial
SP000752 --- Set power value to 752
SP016675 --- Set power value to 16675
Obviously the commands are two types, the first two being booleans and then integers, but I cant seem to find any examples not working off a single ascii character value, which is useless to me. I need more information and then from the message be able to break it down into something the arduino does.
An example of how to import whole commands and either do something, and / or chop the command up to get the value out, would be most useful.
Many thanks in advance :)
EDIT/UPDATE:
I now seem to have found a solution thanks to Edgar as given in the comments. However I now have another question relating to updating the variables so as to effect the loop, as well as performing actions upon receipt of commands (which itself now works)
LINK HERE

There are several parts to this process: Collecting the input; locating the command and the argument (value), validating each of them (is there such a command? Is the value valid?); and finally, acting on the result. What part(s) are you having trouble with?

If you just want an example, you may take a look at this Simple Arduino command line interpreter.

Hi JRobert, sorry I missed the comments section... Essentially I have my output code for each relevant function done, and i currently have seperate arduinos doing about 8 small mundane tasks for a single item. Now I want to combine them and use software to send commands over serial to either update variables the arduino is using or command it to execute various pieces of code.
I will have a look at that Edgar, thank you

Edgar that program seems to do the trick nicely, will have a play and see if I can add my required commands :) - thank you

Hi Edgar, adapting your linked script worked well, I would mark it as the answer but I cant as its a comment - but thank you greatly! :)

as the answer below was deleted, I thought I would provide you with just the links to my post about how it works and the code: the blog is here: https://dannyelectronics.wordpress.com/2017/06/25/worlds-simplest-serial-display-pic16f/. the code is here: https://github.com/dannyf00/Serial-Display.

the piece you want to pay attention to is process(). Very briefly, it takes the serial input, if it is a valid data piece, it updates a circular buffer; if it is a valid command ('\n' or '\r'), it updates the display. Consult the post that has been deleted for more details. Best of luck.

Expanding on my comment... I wrote a simple command line interpreter
that you can use as a base, or an inspiration, for your own interpreter.
In order to not make a link-only answer, I will put here an annotated
and simplified version.
The incoming characters are handled by loop(). They are stored into a
static buffer until a carriage return (CR = '\r') is received. When
the CR is received:

the buffer is NUL-terminated in order to make it a proper C string
it is handed to the exec() function for interpretation
the variable storing the command length is reset to zero for the next
command

Here is the code:
while (Serial.available()) {
    static char buffer[BUF_LENGTH];
    static int length = 0;  // length of line received so far
    int data = Serial.read();
    if (data == '\r') {
        buffer[length] = '\0';     // properly terminate the string
        if (length) exec(buffer);  // give to interpreter
        length = 0;                // reset for next command
    } else if (length < BUF_LENGTH - 1) {
        buffer[length++] = data;   // buffer the incoming byte
    }
}

The exec() interpreter function uses strsep() to split the
command line into a command verb and subsequent parameters. It then
compares the command verb with all supported commands in a long if...
else if sequence, like this:
static void exec(char *cmdline)
{
    char *command = strsep(&cmdline, " ");

    if (strcmp(command, "mode") == 0) {
        int pin = atoi(strsep(&cmdline, " "));
        int mode = atoi(cmdline);
        pinMode(pin, mode);
    } else if (strcmp(command, "read") == 0) {
        int pin = atoi(cmdline);
        Serial.println(digitalRead(pin));
    } else if (strcmp(command, "write") == 0) {
        int pin = atoi(strsep(&cmdline, " "));
        int value = atoi(cmdline);
        digitalWrite(pin, value);
    } else {
        Serial.print(F("Error: Unknown command: "));
        Serial.println(command);
    }
}

This one supports the three commands:

mode <pin> <mode>, meaning pinMode()
read <pin>, meaning digitalRead()
write <pin> <value>, meaning digitalWrite()

The full version is here: Simple Arduino command line
interpreter. Compared to the version in this answer, the
main differences are:

it echoes the characters it reads, and does so in a way which is
friendly to terminal emulators:

it echoes CR as CRLF
it handles BS (backspace) and echoes it as BS + space + BS

it uses strcmp_P() instead of strcmp(), with the PSTR() macro,
in order to keep the constant strings in Flash only
it supports more commands, including "help".

You need to read the serial input into a string(char[]) or String.  You then need to parse that string to read a series of acceptable characters and then convert that into an action.
This is semi-pseudo code (not compiled, not tested, not complete)
bool quit = false;
const int MaxCommand = 10;
char command[MaxCommand];
while (!quit)
{
   int index[0];
   bool wholeCommand = false;
   bool invalidCommand = false;
   while (!wholeCommand && !invalidCommand)
   {
      while (!Serial.available())
        ;
      command[index++] = Serial.read();
      invalidCommand = CheckInvalidCommand();
      wholeCommand = CheckWholeCommand();
   }
   if (invalidCommand)
   {
      Serial.print("That's an invalid command");
   }
   else if (wholeCommand)
   {
      if (strcmp(wholeCommand, "PWR_TRUE") == 0) // 0 means it matches
      {
         power(true);
      }
      else if strcmp(wholeCommand, "PWR_TRUE") == 0) // 0 means it matches
      {
         power (false);
      }
   }
}

However That's the hard way to do it.  A much easier way is to utilities the user's CPU a bit more and get them to type data in a more computer friendly method.  After all users are easier to program, particularly with a base ball bat.
Make you language fixed length:

POWER TRUE |FALSE
REPOR FREQ
SETPW NUMBER

For instance use 5 letters for the command and then until the end of the line for arguments.
Probably the easiest way of manipulating strings for a newbie is to look at the String object class, but the C library string functions maybe the only way to truly get what you want (strcmp, strlen, strtok, strcpy, etc)

EDIT
If you are struggling to code something on the Arduino then what I do is try and knock it up on Visual Studio.  In this case you will need a simulated Serial object.
/// Code to simulate a Serial object on a Windows PC - Not Arduino code!!!
#pragma once
#include <afx.h>

class CSerial
{
public:
    CSerial () {}
    virtual ~CSerial () {}

    void begin (const int& baudRate) {}
    void flush (void) {}
    int available (void) {return 1;}
    unsigned char read (void) {return 42;}

    void print (const char* data) {_tprintf(L"%s", data);}
    void println (const char* data = NULL) {_tprintf(L"%s\n", data);}
    void print (const int& data) {_tprintf(L"%d", data);}
    void println (const int& data) {_tprintf(L"%d\n", data);}
};

static CSerial Serial = CSerial();

You will need to change read() and available() so that they return meaningful data.  You could do this be adding a char[] to the class that is prepopulated with data, such as "POWER TRUE\nREPOR FREQ\nPOWER FALSE" and then use an int as an index into that.

Not having much luck implementing it within my sketch yet, but thank you for the heads up, getting lots of errors to debug that are probably my own doing. The issue I cant get my head around is if i do not send the value with the command and have the arduino do the lifting, how does it know which variable its changing?
I want the arduino to monitor something as failsafe and update values over serial. I am trying to make it user friendly, but at the same time what seems to be a simple goal is becoming seemingly impossible to implement. :(

Read until you see the end of line character '\n' then parse the string you have read.  If the string doesn't contain a space then the command is invalid, ignore the line (show error?) and start reading again.  Is that what you mean?  It really isn't difficult (I appreciate it doesn't feel like that), it might be easier to do with pen and paper, write down what you want to do, break that down into small chunks and then implement each of those chunks as a function.  It will be easier to debug.

If you are on Windows, download visual studio from Microsoft and use that to code and test.  You will need to code a serial object that mocks/fakes the functions you require, but its not difficult.  See edited answer for a starting point.

Perhaps you should consider using https://github.com/j123b567/scpi-parser
It's an API library that allows you to build an 'instrument' that uses a recognized standard 'SCPI' as the communications protocol. It makes your device compliant with an industry standard, and can be implemented using tested code. Your example protocol is pretty SCPI-like already.

Thank you for the suggestion, something I should look into for sure. The code looks a little harder for me to disipher as a noob but I will try and work it out.
Do you happen to know if SCPI is mandatory or just good practice in industry? Thanks

It's far from mandatory; god knows I've had to deal with a a bunch of devices that use their own 'prtocol', and invariably, they are terrible. Probably simple for them to code, but far from simple to handle as an end user. To be able to simply say 'SCPI Compliant' will explain a lot to many people.

Is your device interface intended to interact with humans or with code? If you don't have to cater to human foibles such as forgiveness in commandline editing, it gets easier.


text:
How can I downsize protruding pins from sensors to so I can use a smaller housing?
I'm trying to create a system where I continuously measure color data from a fluid. I've created a 3D-printed box where the pins fit; if they're configured in their out-of-the-box arrangement, what would be the best way to decrease the height of the sensor structure to obtain a more sleek design?
I suppose I could bend the pins as in the picture, but that doesn't sound so great. Would the best solution be de-soldering the out-of-the-box pins, attaching wires with male connectors, and soldering them into the now empty connections? (Although I don't trust my soldering that much, as the pins are very, very close)

@jsotola: the thing should fit into the black box. I have cropped the picture so that it takes less space on the screen.

Buy the sensor without pins and solder the wires directly to the board. You should do that anyway for a better mechanical and electrical connection.
The same applies to the Arduino or other micro-controller. Buy one without header and solder the wires.

Although I don't trust my soldering that much, as the pins are very, very close

Those pins are not close. It seems you haven't seen SMD components yet. They have a standard 2.54 mm (0.1 in) spacing. If you can't do it reliably, let it do someone else. Or go to a local amateur radio club and ask them to teach you soldering. Or maybe you just have the wrong tip for the soldering iron.

Unfortunately, not knowing this, I've finished my project's budget. I suppose I will be either: 1. trying to de-solder all those pins or 2. trying to wrap a wire around the already-in-place pins and solder them instead, then cover them with a shrinking tube. 3. Bite the bullet and pay out of pocket.
I'll train my soldering on some waste bits I've got, I suppose. It can't be harder than brain surgery...
Much appreciate the answer, by the way :)

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Arduino uno toggle switch help
I am building a box that will start a genset. It has two buttons, run and stop.
I would like button run to be able to start (and remain constant) until pressed a second time, I have sussed this bit so far, but this is where I get stuck.
I would like the stop button to only stop the the engine (as a single function)
So my question is how do I integrate the second button (stop) to carry out this one task?
int LEDYelState=0;
int LEDRedState=0;
int LEDGrnState=0;
int RELAYRedState=0;
int RELAYYelState=0;
int RELAYGrnState=0;
int LEDRedPin=10;
int LEDYelPin=9;
int LEDGrnPin=8;
int RELAYRedPin=7;
int RELAYYelPin=6;
int RELAYGrnPin=5;
int buttonPin=13;
int buttonNew;
int buttonOld=1;
int dt=100;
int buttonOff;
int buttonPinOff=12;
void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pinMode(LEDRedPin, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode (LEDYelPin,OUTPUT);
pinMode (LEDGrnPin, OUTPUT);
pinMode (RELAYRedPin, OUTPUT);
pinMode (RELAYYelPin, OUTPUT);
pinMode (RELAYGrnPin, OUTPUT);
pinMode (buttonPinOff, INPUT);
}
void loop() {
buttonNew=digitalRead(buttonPin);
buttonOff=digitalRead(buttonPin);
if(buttonOld==0 && buttonNew==1){
  if (LEDRedState==0){
    digitalWrite(LEDRedPin,HIGH);
    LEDRedState=1;
    digitalWrite(RELAYRedPin,LOW);
    RELAYRedState=1;

    digitalWrite(LEDYelPin, HIGH);
    LEDYelState=1;
    digitalWrite(RELAYYelPin, LOW);
    RELAYYelState=1;
    delay (8000);
    digitalWrite(LEDYelPin,LOW);
    digitalWrite(RELAYYelPin,HIGH);

    digitalWrite (LEDGrnPin,HIGH);
    LEDGrnState=1;
    digitalWrite (RELAYGrnPin, LOW);
    RELAYGrnState=1;
    delay(2000);
    digitalWrite  (LEDGrnPin,LOW);
    digitalWrite (RELAYGrnPin,HIGH);
    RELAYGrnState=1;
  }
  else{
    digitalWrite(LEDRedPin, LOW);
    LEDRedState=0;
    digitalWrite(RELAYRedPin, HIGH);
    RELAYRedState=0;
    digitalWrite(LEDYelPin,LOW);
    LEDYelState=0;

  }
}
buttonOld=buttonNew;
delay(dt);

}

separate the motor run function from the button press function .... declare a boolean variable ... name it run for example ... when it is true, then the engine runs ... when it is false, then the engine stops ... if you press start, then make run true ... if you press start again, then make run false .... when you press stop, then make run false

Could you give me some code that I can see for example that might work ?
Cheers Bryan

A general hint first: indent your code correctly. It makes it much easier to read and easier to spot logical errors.
Another improvement would be to name the pins with the same names as you name them when explaining the problem to us. I expected to find a int buttonRunPin and int buttonStopPin.
The first issue I see is:
buttonNew=digitalRead(buttonPin);
buttonOff=digitalRead(buttonPin);

This reads the same button twice. You probably wanted to read two different buttons: the "run" button and the "stop" button.
The next issue I see is:
delay(8000);
delay(2000);

During these 10 seconds, you can press and let go the button many times. But since there is no digitalRead() during that time, the button press will not be recognized.
The same applies to
int dt=100;
delay(dt);

If you press the button within these 100 ms, it will not be noticed.
Unfortunately, to fix that, you need to learn a completely new concept: interrupts. And even worse, not all pins support interrupts. On the Arduino Uno, it's only pin 2 and pin 3, which means you would need to change your hardware setup (because you use pin 12 and 13). Put both buttons from the pin to ground, so that it closes when pushed.
You would then prepare the interrupt in the setup() routine:
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), toggleRun, CHANGE);
pinMode(buttonPinOff, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPinOff), toggleStopped, CHANGE);

You also define global variables for the state of the buttons:
volatile bool running = false;
volatile bool stopped = false;

volatile is needed here to prevent the compiler from optimizing too much. The compiler does not know about the interrupts and thus can't know when the variable changes.
Next, you need two methods that are being executed whenever an interrupt occurs, i.e. you press a button:
void toggleRun() {
    running = !running;
}
void toggleStopped() {
    stopped = !stopped;
}

Note: the above x = !x; pattern is a short and efficient form of
if (x == false) {
    x = true;
}
else if (x == true) {
   x = false;
}

Once you have all that, you don't need the two digitalRead()s any more.
I'm afraid I haven't understood what your code's supposed to do. You have a lot of state variables that seem to have no use and especially they don't correspond to the motors. E.g. once RELAYGrnState is set to 1, it never changes back to 0.
This is what I have in the end:
int LEDYelState=0;
int LEDRedState=0;
int LEDGrnState=0;
int RELAYRedState=0;
int RELAYYelState=0;
int RELAYGrnState=0;
int LEDRedPin=10;
int LEDYelPin=9;
int LEDGrnPin=8;
int RELAYRedPin=7;
int RELAYYelPin=6;
int RELAYGrnPin=5;
int buttonPin=13;
int buttonNew;
int buttonOld=1;
int dt=100;
int buttonOff;
int buttonPinOff=12;

volatile bool running = false;
void toggleRun() {
    running = !running;
}

volatile bool stopped = false;
void toggleStopped() {
    stopped = !stopped;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(LEDRedPin, OUTPUT);
  pinMode (LEDYelPin,OUTPUT);
  pinMode (LEDGrnPin, OUTPUT);
  pinMode (RELAYRedPin, OUTPUT);
  pinMode (RELAYYelPin, OUTPUT);
  pinMode (RELAYGrnPin, OUTPUT);

  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), toggleRun, CHANGE);
  pinMode(buttonPinOff, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPinOff), toggleStopped, CHANGE);
}

void doSomething() {
  digitalWrite(LEDRedPin,HIGH);   // red LED is on
  LEDRedState=1;
  digitalWrite(RELAYRedPin,LOW);  // red motor off? others unclear
  RELAYRedState=1;

  digitalWrite(LEDYelPin, HIGH);  // yellow LED and red LED are on
  LEDYelState=1;
  digitalWrite(RELAYYelPin, LOW);  // yellow motor off?
  RELAYYelState=1;
  delay (8000);
  digitalWrite(LEDYelPin,LOW);     // red LED on
  digitalWrite(RELAYYelPin,HIGH);  // yellow motor on

  digitalWrite (LEDGrnPin,HIGH);  // red and green LED are on
  LEDGrnState=1;
  digitalWrite (RELAYGrnPin, LOW);  // green motor off
  RELAYGrnState=1;
  delay(2000);
  digitalWrite  (LEDGrnPin,LOW);    // red LED on
  digitalWrite (RELAYGrnPin,HIGH);  // green motor on
  RELAYGrnState=1;
}

void doLess() {
  digitalWrite(LEDRedPin, LOW);     // red LED off
  LEDRedState=0;
  digitalWrite(RELAYRedPin, HIGH);  // red motor on
  RELAYRedState=0;
  digitalWrite(LEDYelPin,LOW);      // yellow LED off
  LEDYelState=0;
}

void loop() {
  if(running){
    if (!stopped){
      doSomething();
    }
    else{
      doLess();
    }
  }
  delay(dt);
}

I’ve taken that all on board, thank you, now I’ll try to get to grips with your advise ..... thanks again

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Are there any products based on Arduino that are sold by companies?
Ok, Arduino is a good technology but is it used professionally? Is the quality good enough to be used for professional purposes?

Quite a few 3d printers have the circuitry of an Arduino and a special motor/heater driver shield combined to form their main circuit board.

In theory, an Arduino board could be used in some low-end professional products (i.e. where the performance and memory limitations aren't an issue). The build quality of the official boards is certainly good enough. The only issue they would potentially have is making suitably robust connections -- i.e. anything plugged into a female header would have the potential to get shaken loose.
In practice though, using an Arduino board would only make sense for extremely small-scale projects, where only a few units will be produced, and where there will be a minimum of external circuitry.
A commercial project would normally have a custom circuit board designed. That allows them to economise on space and features, eliminating unnecessary costs. Even if it only saves a small amount per board, it can make a big difference if you're doing mass-production.
With that said, a professional product could certainly use an AVR microcontroller or similar at its heart (much like the Arduino boards). Atmel was producing chips long before Arduino was around, and their products are well known and widely used. The choice really depends on the needs of the individual project.

We are doing this right now, and it's more than a few cents difference. Our prototype (Arduino, sensors, wiring) costs about $45. Our boards will cost about $5 and could be cheaper if we make a lot of them.

@Jasmine - Thanks for sharing some real values. I've clarified my wording so it's hopefully better now.

Just to be totally clear... that's the retail cost of Arduino boards and breakout boards, along with prototyping tools like breadboards and wires. The $5 is a hard price point to hit, and most of that is the Atmel chip, but that's our estimate for wholesale cost of our boards. The product itself needs a case and some documentation as well as packaging, so don't forget to add that in.

Yes, you can also use an Arduino for professional usage. The Arduino is actually just a prototyping device and easy to use for people at home/school. I suppose there might be products on the market which were developed using an Arduino. But the most important thing is the Atmel MCU inside the Arduino which can be used for anything. But, if you wanna know if the ATmega328P-PU which is used in the Arduino Uno is a common MCU used by professionals? The answer would be no. Everything has to be smaller and better so it'll be more likely to find the same MCU like the Arduino Leonardo, Mega etc etc.
Examples where professionals might use an Arduino for as base (The end product will only contain the MCU of the Arduino):

Kid toys like an Simon Says Game, Line following toy cars etc etc.
Small industrial products like an automated tape dispenser.
AVR programmers.
Card readers.

Yes, I work for an engineering design house and we use Arduino frequently to prototype ideas for clients.  It significantly speeds up the time to get a proof-of-concept device in the hands of the client and their potential investors.
We have found though that there is significant work to get from an Arduino-based prototype to a commercially-ready product.  Essentially you have to start again and design a completely custom printed circuit board, which is a relatively expensive exercise.
We are now developing a platform that is compatible with the Arduino IDE, but uses surface-mount modules rather than the Arduino shield system, allowing it to be manufactured in an automated surface-mount facility.  Check it out if you are interested at duinopro.cc.  We are in development stages at the moment, but already have hardware and are mainly working on our website, and designing new modules.

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Warning Arduino CMakeLists "Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES"
I'm trying to build an Arduino example without using its IDE. My OS is Windows 8.1 and I'm using the last version of CMake (2.8.12.2) and MinGW (GNU Make 3.82.90).
I downloaded the Arduino CMakeLists and I learned all about make/upload any firmware in my Arduino. I'm using Arduino UNO.
Then, if I modify the CMakeLists saved in ~/arduino-cmake-master/example/CMakeLists.txt (arduino-cmake-master is the repository folder) to build the WiFi example WiFiWebClient too:
...

#Add the WiFi example -> WiFiWebClient
generate_arduino_example(wifi_example
                     LIBRARY WiFi
                     EXAMPLE WiFiWebClient)
...

And execute:
  $ cmake -G "MinGW Makefiles"

  ...

  CMake Warning (dev) in example/CMakeLists.txt:
  Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link
  interface.  Run "cmake --help-policy CMP0022" for policy details.  Use the
  cmake_policy command to set the policy and suppress this warning.

  Target "uno_example" has an INTERFACE_LINK_LIBRARIES property.  This should
  be preferred as the source of the link interface for this library but
  because CMP0022 is not set CMake is ignoring the property and using the
  link implementation as the link interface instead.

  INTERFACE_LINK_LIBRARIES:

    uno_CORE;uno_example;uno_Wire

  Link implementation:

    uno_CORE;uno_Wire

This warning is for project developers.  Use -Wno-dev to suppress it.

CMake Warning (dev) in example/CMakeLists.txt:
  Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link
  interface.  Run "cmake --help-policy CMP0022" for policy details.  Use the
  cmake_policy command to set the policy and suppress this warning.

  Target "uno_Wire" has an INTERFACE_LINK_LIBRARIES property.  This should be
  preferred as the source of the link interface for this library but because
  CMP0022 is not set CMake is ignoring the property and using the link
  implementation as the link interface instead.

  INTERFACE_LINK_LIBRARIES:

    uno_CORE;uno_Wire

  Link implementation:

    uno_CORE

This warning is for project developers.  Use -Wno-dev to suppress it.

CMake Warning (dev) in example/CMakeLists.txt:
  Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link
  interface.  Run "cmake --help-policy CMP0022" for policy details.  Use the
  cmake_policy command to set the policy and suppress this warning.

  Target "uno_SPI" has an INTERFACE_LINK_LIBRARIES property.  This should be
  preferred as the source of the link interface for this library but because
  CMP0022 is not set CMake is ignoring the property and using the link
  implementation as the link interface instead.

  INTERFACE_LINK_LIBRARIES:

    uno_CORE;uno_SPI

  Link implementation:

    uno_CORE

This warning is for project developers.  Use -Wno-dev to suppress it.

CMake Warning (dev) in example/CMakeLists.txt:
  Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES defines the link
  interface.  Run "cmake --help-policy CMP0022" for policy details.  Use the
  cmake_policy command to set the policy and suppress this warning.

  Target "uno_WiFi" has an INTERFACE_LINK_LIBRARIES property.  This should be
  preferred as the source of the link interface for this library but because
  CMP0022 is not set CMake is ignoring the property and using the link
  implementation as the link interface instead.

  INTERFACE_LINK_LIBRARIES:

    uno_CORE;uno_WiFi

  Link implementation:

    uno_CORE

This warning is for project developers.  Use -Wno-dev to suppress it.

-- Generating done
-- Build files have been written to: ~/arduino-cmake-master

Later I execute:
$ mingw32-make

...

Linking CXX static library libuno_WiFi.a
[ 89%] Built target uno_WiFi
Scanning dependencies of target wifi_example
[ 92%] Building CXX object example/CMakeFiles/wifi_example.dir/wifi_example_WiFiWebClient.cpp.obj
Linking CXX executable wifi_example.elf
libuno_WiFi.a(WiFiClient.cpp.obj): In function `WiFiClient::status()':
C:\Program Files\Arduino\libraries\WiFi/WiFiClient.cpp:160: undefined reference to `ServerDrv::getClientState(unsigned char)'
libuno_WiFi.a(WiFiClient.cpp.obj): In function `WiFiClient::stop()':
C:\Program Files\Arduino\libraries\WiFi/WiFiClient.cpp:131: undefined reference to `ServerDrv::stopClient(unsigned char)'
libuno_WiFi.a(WiFiClient.cpp.obj): In function `WiFiClient::peek()':
C:\Program Files\Arduino\libraries\WiFi/WiFiClient.cpp:117: undefined reference to `ServerDrv::getData(unsigned char, unsigned char*, unsigned char)'
libuno_WiFi.a(WiFiClient.cpp.obj): In function `WiFiClient::read()':
C:\Program Files\Arduino\libraries\WiFi/WiFiClient.cpp:101: undefined reference to `ServerDrv::getData(unsigned char, unsigned char*, unsigned char)'
libuno_WiFi.a(WiFiClient.cpp.obj): In function `WiFiClient::read(unsigned char*, unsigned int)':
C:\Program Files\Arduino\libraries\WiFi/WiFiClient.cpp:107: undefined reference to `ServerDrv::getDataBuf(unsigned char, unsigned char*, unsigned int*)'
libuno_WiFi.a(WiFiClient.cpp.obj): In function `WiFiClient::available()':
C:\Program Files\Arduino\libraries\WiFi/WiFiClient.cpp:90: undefined reference to `ServerDrv::availData(unsigned char)'
libuno_WiFi.a(WiFiClient.cpp.obj): In function `WiFiClient::write(unsigned char const*, unsigned int)':
C:\Program Files\Arduino\libraries\WiFi/WiFiClient.cpp:73: undefined reference to `ServerDrv::sendData(unsigned char, unsigned char const*, unsigned int)'
C:\Program Files\Arduino\libraries\WiFi/WiFiClient.cpp:78: undefined reference to `ServerDrv::checkDataSent(unsigned char)'
libuno_WiFi.a(WiFiClient.cpp.obj): In function `WiFiClient::connect(IPAddress, unsigned int)':
C:\Program Files\Arduino\libraries\WiFi/WiFiClient.cpp:36: undefined reference to `ServerDrv::startClient(unsigned long, unsigned int, unsigned char, unsigned char)'
libuno_WiFi.a(WiFi.cpp.obj): In function `WiFiClass::hostByName(char const*, IPAddress&)':
C:\Program Files\Arduino\libraries\WiFi/WiFi.cpp:228: undefined reference to `WiFiDrv::getHostByName(char const*, IPAddress&)'
libuno_WiFi.a(WiFi.cpp.obj): In function `WiFiClass::status()':
C:\Program Files\Arduino\libraries\WiFi/WiFi.cpp:223: undefined reference to `WiFiDrv::getConnectionStatus()'
libuno_WiFi.a(WiFi.cpp.obj): In function `WiFiClass::RSSI()':
C:\Program Files\Arduino\libraries\WiFi/WiFi.cpp:181: undefined reference to `WiFiDrv::getCurrentRSSI()'
libuno_WiFi.a(WiFi.cpp.obj): In function `WiFiClass::SSID()':
C:\Program Files\Arduino\libraries\WiFi/WiFi.cpp:169: undefined reference to `WiFiDrv::getCurrentSSID()'
libuno_WiFi.a(WiFi.cpp.obj): In function `WiFiClass::localIP()':
C:\Program Files\Arduino\libraries\WiFi/WiFi.cpp:149: undefined reference to `WiFiDrv::getIpAddress(IPAddress&)'
libuno_WiFi.a(WiFi.cpp.obj): In function `WiFiClass::begin(char*, char const*)':
C:\Program Files\Arduino\libraries\WiFi/WiFi.cpp:87: undefined reference to `WiFiDrv::wifiSetPassphrase(char*, unsigned char, char const*, unsigned char)'
C:\Program Files\Arduino\libraries\WiFi/WiFi.cpp:92: undefined reference to `WiFiDrv::getConnectionStatus()'
libuno_WiFi.a(WiFi.cpp.obj): In function `WiFiClass::init()':
C:\Program Files\Arduino\libraries\WiFi/WiFi.cpp:22: undefined reference to `WiFiDrv::wifiDriverInit()'
example\CMakeFiles\wifi_example.dir\build.make:95: recipe for target 'example/wifi_example.elf' failed
mingw32-make[2]: *** [example/wifi_example.elf] Error 1
CMakeFiles\Makefile2:748: recipe for target 'example/CMakeFiles/wifi_example.dir/all' failed
mingw32-make[1]: *** [example/CMakeFiles/wifi_example.dir/all] Error 2
Makefile:74: recipe for target 'all' failed
mingw32-make: *** [all] Error 2

The problem is the Arduino.cmake because it's not linking correctly with the library WiFi, but it links with the Wire library.
Anyone knows why that warning appears and why Wire links ok but WiFi doesn't?
Thanks!
Note: I'm using original code which is in the repository example, I've not modified this one.

Can you confirm that you could generate the examples BEFORE modifying CMakeLists.txt? Also, did you modify something else in this file?

The warning given by cmake does not seem to be a problem (I got the same warning for one of my example projects and it works fine afterwards). Have you tried using another generator (I'm using "Unix Makefiles" and it works fine for my project; I just had to install a Windows version of make).

Another point: did you try generate_arduino_library(WiFi...) first, defining all headers and source files included in WiFi directory? Indeed, I don't think cmake will be able to build the library properly as it should not be able to find files in subdirectory utility: these are the files that contain definitions that mingw32-make is complaining about.

Related to my previous comment, a faster option that you could try is set(WiFi_RECURSE True); it tells cmake to compile all files including those in subdirectories of the WiFi library.

Your question actually has 2 distinct parts:

Why does arduino-cmake generate the warning "Policy CMP0022 is not set: INTERFACE_LINK_LIBRARIES..."?
Why does make, using the generated MakeFile, fail when building WiFi example?

First off, the arduino-cmake "Policy CMP0022" is just a warning, not an error. As per this cmake article, that CMP policy has been only recently introduced in CMake 2.8.12.
You get this warning simply because arduino-cmake has been created based on an older version of cmake and thus does not specifically support this new policy.
In order to get rid of this warning, the documentation mentions you should add the cmake_policy(SET CMP0022 OLD) command to your cmake configuration.
Unfortunately I tried it in the example CMakeLists.txt to no avail; maybe it has to be set directly in arduino-cmake files (which I have not tested).
Thus, if you want to get rid of this boring warning, it seems the only solution you are left with is to disable all warnings when launching cmake:

cmake -G "MinGW Makefiles" -Wno-dev

This works fine and has removed all warnings..
Your second problem (the real one I would say) is due to to the structure of WiFi library:

Indeed, as you can see above, it has a utility subdirectory that contains additional source code that cannot be found by arduino-cmake, as by default it searches for source code files only at first level directory.
How to solve it? Just tell arduino-cmake to do a recursive search for the WiFi library; in your CMakeLists.txt, ensure you add the following line:
set(WiFi_RECURSE True)
generate_arduino_example(wifi_example
                     LIBRARY WiFi
                     EXAMPLE WiFiWebClient)

The added set(WiFi_RECURSE True) line just tells arduino-cmake that, for WiFi library, it should recurse through subdirectories when looking for source code.
I have checked it with "Unix Makefiles" (not "MinGW Makefiles" but I guess that won't make any difference) and it worked fine.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Serial.read has garbled data after a Serial.write
I'm using the Serial1 of the Arduino Leonardo to send and receive data with another MCU. The following code will always retrieve garbled data:
byte streamReadResponse;
Serial1.begin(115200);
Serial1.setTimeout(9000);
Serial1.print(cmd);
Serial1.print('\r');
Serial1.flush();  //wait for all the data to be sent to the serial
streamReadResponse = Serial1.readBytesUntil('>', data, dataLength);

But, if I add a delay(50) before the Serial1 read, I would get the expected output. The value 50 was found by trial and error.
What am I missing? Why is the flush() command not working as expected?

Could you please tell more about "garbled data". You mean what it is inside your "data" variable? What is the final value of streamReadResponse after the call to readBytesUntil with and without the delay?

Try putting a ~2.2k pull-down resistor on the Arduino's RX pin (connect the resistor to ground and the pin).

Which version of Arduino IDE are you using? It seems HardwareSerial.cpp has changed a lot along different versions, in particular the flush() method. In version 1.0.5 it should be OK normally.

This question really is not answerable without more details, such as the nature of the garbled data as already requested.  It appears to have been abandoned and should probably be closed.

@ChrisStratton you are right - I was not even sure on how to provide the details - I still hope my own answer can help other people.

I've finally found that when the MCU  to which Arduino is talking to was initialized, it would send spurious data to the Serial - I guess it would start first with a lower baud rate, and then switch to the programmed baud rate of 115200.
To fix this, I had to flush the Arduino serial RX before sending any data. So:
byte streamReadResponse;
Serial1.begin(115200);
Serial1.setTimeout(9000);
while (Serial1.read() >= 0)
           ; // do nothing
Serial1.print(cmd);
Serial1.print('\r');
Serial1.flush();  //wait for all the data to be sent to the serial
streamReadResponse = Serial1.readBytesUntil('>', data, dataLength);

Usually, this kind of issue is the result of the several times by time unity of loop statements execution, with the baudrate defined for your serial i/o it's very possible that the flush are override by the new information input and the result are the "garbage" on that.
On my sketches, ever I put "idle function calls"  in some points of the code to avoid this and works succesfully.

I don't understand why this would be. Surely .flush() should do as documented unless Roberto has overridden it?

I don't know why, but, for example, for prevent in a project the malfunction of a clock module, I must call to read it fewer than times, when the documentation not tell nothing about this.The fact is that many times the execution speed of the main loop can make some features of functions and/or response of devices will be wrong. As if you push data onto a funnel and arrives to the exit mistaken.

.flush() pauses execution until the output buffer is empty.  It shouldn't have anything to do with garbage on your input.  Try putting a ~2.2k+- pull-down resistor between serial-in and ground to make sure you aren't getting noise or cross talk in the input buffer.


text:
Modbus master slave
I need Help in two thing Here.
1)My main project is i have 23 hallsensors with analog output. There are connected to arduino UNO analog pins using 16:1 Mux or 8:1 mux circuit. The currently i can receive data properly with proper switching. Which are floating point values.
Second stage: Now this has to communicate via MODbus protocol .(here only transmission is pending)
2) Now I am in to transmission data. Here i am using basic library downloaded from
[Download link modbus library][1]
Now my setup is like this
I have arduino Board. RS485 sheild and USB to RS485 converter. Qmodbus software to view data.
I have uploaded the below code.
#include <ModbusRtu.h>

// data array for modbus network sharing
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, -1 };

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI
 *               or any pin number > 1 for RS-485
 */
Modbus slave(1,0,0); // this is slave @1 and RS-232 or USB-FTDI

void setup() {
  slave.begin( 9600 ); // baud-rate at 19200
}

void loop() {
  slave.poll( au16data, 16 );
}

so i am expecting this answer if i am not wrong.
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, -1 };

But i am getting data as below.
questions:
1) Whats making wrong to get below data??
2)If i want to store float values how can name uint16_t au16data[16] or changes to be made
3) Is there any working code ON modbus![OUTPUt of MODBUS][2]
Finally i got it working i can read The values. Now i am in second part. I have totally 20 values . currently i stored them as integer only. But my values are flaoting point.How to split real & floating value store in au16data[16] register.???
Assume i got my Sensor value converted as
*
CS=30.10
Int_CS=int(CS)
FLOAT_CS=(Int_CS-CS)*100
How to store the Int_CS & FLOAT_CS values in au16data[0]??

*

In Modbus protocol, coils are bits and registers are 16-bit unsigned integers.
Hence if you ask Modbus to read your au16data array as coils, and not as registers (which is what they actually are), then you'll get the binary representation for them with QModbus:
Your first register is 3 which is 0000 0000 0000 0011 in binary. Then when you read it as an array of 16 cils, you get these bit values, in reverse order (bit 0 is the lowest order bit and bit 15 is the highest order bit of your register); this is exactly what QModbus shos you:

First 2 bits are 1
All other bits are 0

Now regarding float values, if I remember correctly this is just not possible with Modbus protocol, hence you cannot do it out of the box.
What you can do, however, is to cast one float as 2 registers and transmit it this way, then it is up to the Modbus client to cast it back to a float; but QModbus will not do that for you as it strictly follows Modbus standard.

what i need to alter in above code to get like as array buffer.Is there any software avialble to view data as it is.uint16_t au16data[16] is register and save data in the form of bits.

When you choose a protocol (modbus) you need to comply with its limitations, or select another protocol!

If you want to see your array values as words not bits, then just tell QModbus to "read registers" instead of "read coils" that is all.

Ya it worked When i comment Read coil function to run only read register function In program. Now my question in second part How to keep real value and floating value in register of word au16data[16]


text:
Serial Request error
I am working on arduino Uno board.I am trying to send request Serially from out Side using docklight.I am sending COmmand  is request send every 5S to 10S and get response.When i tested this code with arduino Uno board its working fine. When i tested same code with Customised board whos schematic as below
. For this i got response like this. I am suspecting it might be issue with crystal. I have replace KDS16 with SCTF16.00crystals . It behave same.Can someone suggest what might be wrong

My code
#include "glob.h"
const int BUFFER_SZ = 32;
char sendBuffer[200];
static int OverRide=0;

void Take_Reading() {

  for (int row = 0; row < 8; row++)
  {
    //   // get rid of me:
    digitalWrite(SO_enable, array[row][0]);
    digitalWrite(S1_enable, array[row][1]);
    digitalWrite(S2_enable, array[row][2]);
    delay(50);
    analog_1_pv[row] = ANALOG_SCALING * analogRead(A0);
    analog_2_pv[row] = ANALOG_SCALING * analogRead(A1);
    analog_3_pv[row] = ANALOG_SCALING * analogRead(A2);
    if ( (analog_1_pv[row] <= MINV_RANGE || (analog_1_pv[row] >= MAXV_RANGE) ))
    {
      Current_Value1[row] =  0.0;
    }
    else
    {
      Current_Value1[row] =  (analog_1_pv[row] * 12.5) - 31.25;

    }

    if (  (analog_2_pv[row] <= MINV_RANGE || (analog_2_pv[row] >= MAXV_RANGE) ))
    {
      Current_Value2[row] =  0.0;
    }
    else
    {
      Current_Value2[row] =  (analog_2_pv[row] * 12.5) - 31.25;

    }

    if (  (analog_3_pv[row] <= MINV_RANGE || (analog_3_pv[row] >= MAXV_RANGE) ))
    {
      Current_Value3[row] =  0.0;
    }
    else
    {
      Current_Value3[row] =  (analog_3_pv[row] * 12.5) - 31.25;

    }

    Mod_current[row] = (uint16_t)(Mul_Factor * Current_Value1[row]);
    Mod_current[row + 8] = (uint16_t)(Mul_Factor * Current_Value2[row]);
    Mod_current[row + 16] = (uint16_t)(Mul_Factor * Current_Value3[row]);

  }

}

int ID_Check() {

  int ID_value;
  for (int row = 0; row < 8; row++)
  {
    digitalWrite(SO_enable, array[row][0]);
    digitalWrite(S1_enable, array[row][1]);
    digitalWrite(S2_enable, array[row][2]);
    Status_Out[row] = digitalRead(Output_Read);

  }

  ID_value = 1 * Status_Out[7] + 2 * Status_Out[6] + 4 * Status_Out[5] + 8 * Status_Out[4] + 16 * Status_Out[3] + 32 * Status_Out[2] + 64 * Status_Out[1] + 128 * Status_Out[0];
  return (ID_value);

}

int  Take_Temp_Reading()
{

  Temp_Total = Temp_Total - Temp_readings[Temp_index];
  Temp_readings[Temp_index] = analogRead(A5);
  Temp_Total = Temp_Total + Temp_readings[Temp_index];
  Temp_index = Temp_index + 1;

  if (Temp_index >= numReadings)
  {
    Temp_index = 0;
    Temp_Average = Temp_Total / numReadings;
  }
  temp = (Temp_Average * 5.0) / 1023.0;

  //  temp = float(analogRead(A5)) * 5.0 / 1024.0;
  temp_int = (int)(temp * 100.0);
  return (temp_int);
  // Serial.print("Temp"); Serial.println(temp);
}

int SPD_Check()
{

  SPD_STATUS = digitalRead(SPD_STATUS_PIN);
  return (SPD_STATUS);
}

int  DC_Status()
{

  DC_STATUS = digitalRead(DC_STATUS_PIN);
  return (DC_STATUS);

}

int   Take_HV_Reading()
{

  //int analog_int= analogRead(A4);

  total = total - readings[index];
  // read from the sensor:
  readings[index] = analogRead(A4);
  // add the reading to the total:
  total = total + readings[index];
  // advance to the next position in the array:
  index = index + 1;

  // if we're at the end of the array...
  if (index >= numReadings1)
  {
    index = 0;
    average = total / numReadings1;

  }
  else
  {

    HV_voltage = (average * 5.0) / 1023.0;
  }
  if (HV_voltage <= 0.25)
  {

    Conv_HV_voltage = 0.0;
  }
  else
  {
    Conv_HV_voltage = 197.837837838 * HV_voltage + 10.8108108108;
  }

  HV_Reading = (uint16_t)(Conv_HV_voltage * 10);

  //  HV_Reading = (uint16_t)(Conv_HV_voltage * 10);

  return(HV_Reading);
}

void  Serial_Command1()

{
  Take_Reading();
  int Temp_read=Take_Temp_Reading();
  int HV_Read=Take_HV_Reading();
  SPD=SPD_Check();
  DISCONNECTOR=DC_Status();
  // Device_ID=ID_Check();
  Device_ID=1;
  Serial.print("SMCB1");
  Serial.print(",");
  Serial.print(Device_ID);
  Serial.print(",");
  for (int i = 0; i < 14; i++) {
    Serial.print(Mod_current[i]);
    Serial.print(",");
  }

  for (int i = 23; i > 13; i--) {
    Serial.print(Mod_current[i]);
    Serial.print(",");
  }

  Serial.print(Temp_read);
  Serial.print(",");
  Serial.print(HV_Read);
  Serial.print(",");
  Serial.print(SPD);
  Serial.print(",");
  Serial.print(DISCONNECTOR);
  Serial.print(",");
  Serial.print(DISCONNECTOR);
  Serial.print(",");
  Serial.println("END");
}

void Serial_Command2(int a)
{
  Take_Reading();
  int Temp_read=Take_Temp_Reading();
  int HV_Read=Take_HV_Reading();
  SPD=SPD_Check();
  DISCONNECTOR=DC_Status();
  Device_ID=1;
  // Serial.print("Command2 executed: ");
  snprintf(sendBuffer, a, "SMCB1,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ,END",Device_ID,
  Mod_current[0], Mod_current[1], Mod_current[2], Mod_current[3],
  Mod_current[4], Mod_current[5], Mod_current[6], Mod_current[7],
  Mod_current[8], Mod_current[9], Mod_current[10], Mod_current[11],
  Mod_current[12], Mod_current[13], Mod_current[14], Mod_current[23],
  Mod_current[22], Mod_current[21], Mod_current[20], Mod_current[19],
  Mod_current[18], Mod_current[17], Mod_current[16], Mod_current[15],
  Mod_current[14], Temp_read, HV_Read, SPD, DISCONNECTOR);
  Serial.println(sendBuffer);
  //Serial.println(a);
}

void setup()
{
  Serial.begin(57600);
  Serial.println("Format 1: <SMCB1,1>");
  Serial.println("Format 2: <SMCB1,1,Length>");
  Serial.println("Format 2: <SMCB1,1,Length,ON> ON- turn on timer ,off to turn off timer");
}

// Parse the request, WITHOUT the '<' and '>' delimiters.
void parseRequest(char *request)
{
  // Check the request starts with the prefix "SMCB1,1".
  if (strncmp(request, "SMCB1,1", 7) != 0) {
    Serial.println(F("Error: bad request prefix"));
   //  Serial_Command1();
    return;
  }

  // Remove that known prefix.
  // Now we have either "", ",Length" or ",Timer,On_OFF"
  request += 7;

  // Format 1: ""
  if (request[0] == '\0') {
    //Serial.println(F("Received format 1"));
    Serial_Command1();
    return;
  }

  // Remove the leading comma.
  // Now we have either "Length" or "Timer,On_OFF"
  if (request[0] != ',') {
    Serial.println(F("Error: ',' expected"));
    return;
  }
  request++;

  // Format 2: "Length", no comma.
  char * comma = strchr(request, ',');
  if (!comma) {

    int length = atoi(request);
    Serial_Command2(length);
    //Serial.print(F("Received format 2, length = "));
    // Serial.println(length);
    return;
  }

  // format 3
  int timer = atoi(request);
  char * on_off = comma + 1;
  char * Compare="ON";
  bool on = strcmp(on_off, "ON") == 0;
  if (!on && strcmp(on_off, "OFF") != 0) {  // sanity check
    Serial.println(F("Error: expected either ON or OFF"));
    return;
  }
  /*  Serial.print(F("Received format 3, timer = "));
   Serial.print(timer);
   Serial.print(F(", on_off = "));
   Serial.println(on ? "ON" : "OFF");
   Serial.println(on_off);
   Serial.println(Compare);*/
  int v = strcmp(on_off, Compare);
  if(v==0)
  {
    Serial.println("Timer is on");
    OverRide=1;

  }
  else
  {
    Serial.println("Timer is OFF");
    OverRide=0;
  }

}

void loop()
{
  static char buffer[BUFFER_SZ];  // received chars
  static size_t pos;              // current position in buffer
  static bool insideRequest;      // are we between '<' and '>'?

  if (Serial.available()) {
    char c = Serial.read();
    if (insideRequest) {
      if (c == '>') {  // end of request received
        buffer[pos] = '\0';  // terminate the string
        parseRequest(buffer);
        pos = 0;             // get ready for the next request
        insideRequest = false;
      }
      else if (pos < BUFFER_SZ-1) {  // add char to buffer
        buffer[pos++] = c;
      }
    }
    else if (c == '<') {  // start of request
      insideRequest = true;
    }

  }

}

Test your custom board with a much simpler sketch, for example one that just gives a simple serial output or maybe counts, and edit exactly what you receive compared to what is expected into your question.  It is worrisome that there does not seem to be a ground connection on the serial header on this custom board - you must have a common ground with the other end of the serial link.

i dont have problem in receving data. I tested already. I am printing Serial statement for Every 1S-10S code seem wok fine.

I tested code with Simple [print statement . Where i can able to receive data without any garbage value or miss of data.Yes i have connected Common Ground connection.I am worried code working fine over Arduino not over customised board.Whenever change crystal ,For some crystal more response coming normally.i.e out of 10 request i am getting error for 2

Could you post a photo of the board? The traces to the crystal might be too long e.g.. Could you use a lower speed, than 57600 baud.

@Gerben This baudrate required to communicate with Wifi device. WIth same board out of 10 board 3 boards are working as i expected. But remaining boards have same Serial print issue. Either it wont print data or Taking request with Data missed.

Could you post a photo of the board?


text:
Modbus Protocol RTU
I have simple code working on Serial Communication asn below. With Same data i would impliment Modbus protocol> I have Used Modbus library for arduino earlier which works fine with 9600 baudrate and wont work with higher baudrates.And also have restriction In library ,They directly storing values into Buffers SO i cant able to fig out weather request send proper or improper.
I never Worked on EMbeded c Chip level code.Is there any way to Implement without library for arduino
In below code I would Like Serial value into register and when function called i could read value. Similarly the function CODE for Modbus should be implemented.
I am looking for simple c code or implement c code Where i can perform the operation this way.
I am trying to Send modbus Request
I found CRC error calculation like in one of forum
 unsigned int crc_fn(unsigned char *dpacket,unsigned int len)    // CRC 16 Function(Error calculation)
    {
        unsigned int crc = 0xffff,poly = 0xa001;
        unsigned char i=0,j=0;

        for(i=0;i<len;i++)
        {
            crc^= dpacket[i];
            for(j=0;j<8;j++)
            {
                if(crc & 0x01)
                {
                    crc >>= 1;
                    crc ^= poly;
                }
                else
                crc >>= 1;
            }
        }
        return (crc);
    }

I would like to See my code in arduino Like this With CRC check
void Serial_access(void)
{
    unsigned char i=0,len=0,ser_data[60],crc_data[60],j=0;
    unsigned int crc1=0,crc2=0;
    crc1 = crc_fn(&rxbuf[0],6);
    _delay_ms(100);
    if((rxbuf[6] == (unsigned char)(crc1))&&(rxbuf[7] == (unsigned char)(crc1>>8)))
    {
        if(rxbuf[0]==DEVICE_ID)
        {
            if(rxbuf[1] == Function_code)
            {
                if((rxbuf[5]>=1)&&(rxbuf[5]<30))
                {
                    //Address = ((unsigned int)(rxbuf[2]<<8)+((unsigned int)(rxbuf[3])));
                    len = (rxbuf[5]*2);
                    _delay_ms(10);
                    ser_data[0] = 0;
                    ser_data[1] = 0;
                    ser_data[2] = 0;
                    ser_data[3] = 0;
                    ser_data[4] = 0;
                    ser_data[5] = 0;
                    ser_data[6] = 0;
                    ser_data[7] = 0;
                    ser_data[8] = 0;
                    ser_data[9] = 0;
                    ser_data[10] = 0;
                    ser_data[11] = 0;
                    ser_data[12] = 0;
                    ser_data[13] = 0;
                    ser_data[14] = 0;
                    ser_data[15] = 0;
                    ser_data[16] = 0;
                    ser_data[17] = 0;
                    ser_data[18] = 0;
                    ser_data[19] = 0;
                    ser_data[20] = 0;
                    ser_data[21] = 0;
                    ser_data[22] = 0;
                    ser_data[23] = 0;
                    ser_data[24] = 0;
                    ser_data[25] = 0;
                    ser_data[26] = 0;
                    ser_data[27] = 0;
                    ser_data[28] = 0;
                    ser_data[29] = 0;
                    ser_data[30] = 0;
                    ser_data[31] = 0;
                    ser_data[32] = 0;
                    ser_data[33] = 0;
                    ser_data[34] = 0;
                    ser_data[35] = 0;
                    ser_data[36] = 0;
                    ser_data[37] = 0;
                    ser_data[38] = 0;
                    ser_data[39] = 0;
                    ser_data[40] = 0;
                    ser_data[41] = 0;
                    ser_data[42] = 0;
                    ser_data[43] = 0;
                    ser_data[44] = 0;
                    ser_data[45] = 0;
                    ser_data[46] = 0;
                    ser_data[47] = 0;
                    ser_data[48] = 0;
                    ser_data[49] = 0;
                    ser_data[50] = 0;
                    ser_data[51] = 0;
                    ser_data[52] = 0;
                    ser_data[53] = 0;
                    ser_data[54] = 0;
                    ser_data[55] = 0;
                    ser_data[56] = 0;
                    ser_data[57] = 0;
                    ser_data[58] = 0;

                    crc_data[0] = DEVICE_ID;
                    crc_data[1] = Function_code;
                    crc_data[2] = len;

                    j=3;
                    for(i=0;i<len;i++)
                    {
                        crc_data[j++] = ser_data[i];
                    }
                    crc2 = crc_fn(&crc_data[0],(len+3));
                    _delay_ms(100);
                    serial_send(DEVICE_ID);
                    serial_send(Function_code);
                    serial_send(len);
                    for(i=0;i<len;i++)
                    {
                        serial_send(ser_data[i]);
                    }
                    _delay_ms(10);
                    serial_send((unsigned char)(crc2));
                    serial_send((unsigned char)(crc2>>8));
                }
            }
        }
    }
    index = 0;
    for(i=0;i<16;i++)
        rxbuf[i] = 0;
    rec_flag = 0;
    check_flag = 1;
}

Here code written in C++, How can we convert these to C
int8_t Modbus::query( modbus_t telegram ) {
  uint8_t u8regsno, u8bytesno;
  if (u8id != 0) return -2;
  if (u8state != COM_IDLE) return -1;

  if ((telegram.u8id == 0) || (telegram.u8id > 247)) return -3;

  au16regs = telegram.au16reg;

  // telegram header
  au8Buffer[ ID ]         = telegram.u8id;
  au8Buffer[ FUNC ]       = telegram.u8fct;
  au8Buffer[ ADD_HI ]     = highByte(telegram.u16RegAdd );
  au8Buffer[ ADD_LO ]     = lowByte( telegram.u16RegAdd );

  switch ( telegram.u8fct ) {
  case MB_FC_READ_COILS:
  case MB_FC_READ_DISCRETE_INPUT:
  case MB_FC_READ_REGISTERS:
  case MB_FC_READ_INPUT_REGISTER:
    au8Buffer[ NB_HI ]      = highByte(telegram.u16CoilsNo );
    au8Buffer[ NB_LO ]      = lowByte( telegram.u16CoilsNo );
    u8BufferSize = 6;
    break;
  case MB_FC_WRITE_COIL:
    au8Buffer[ NB_HI ]      = ((au16regs[0] > 0) ? 0xff : 0);
    au8Buffer[ NB_LO ]      = 0;
    u8BufferSize = 6;
    break;
  case MB_FC_WRITE_REGISTER:
    au8Buffer[ NB_HI ]      = highByte(au16regs[0]);
    au8Buffer[ NB_LO ]      = lowByte(au16regs[0]);
    u8BufferSize = 6;
    break;
  case MB_FC_WRITE_MULTIPLE_COILS:
    u8regsno = telegram.u16CoilsNo / 16;
    u8bytesno = u8regsno * 2;
    if ((telegram.u16CoilsNo % 16) != 0) {
      u8bytesno++;
      u8regsno++;
    }

    au8Buffer[ NB_HI ]      = highByte(telegram.u16CoilsNo );
    au8Buffer[ NB_LO ]      = lowByte( telegram.u16CoilsNo );
    au8Buffer[ NB_LO + 1 ]    = u8bytesno;
    u8BufferSize = 7;

    u8regsno = u8bytesno = 0; // now auxiliary registers
    for (uint16_t i = 0; i < telegram.u16CoilsNo; i++) {

    }
    break;

  case MB_FC_WRITE_MULTIPLE_REGISTERS:
    au8Buffer[ NB_HI ]      = highByte(telegram.u16CoilsNo );
    au8Buffer[ NB_LO ]      = lowByte( telegram.u16CoilsNo );
    au8Buffer[ NB_LO + 1 ]    = (uint8_t) ( telegram.u16CoilsNo * 2 );
    u8BufferSize = 7;

    for (uint16_t i = 0; i < telegram.u16CoilsNo; i++) {
      au8Buffer[ u8BufferSize ] = highByte( au16regs[ i ] );
      u8BufferSize++;
      au8Buffer[ u8BufferSize ] = lowByte( au16regs[ i ] );
      u8BufferSize++;
    }
    break;
  }

  sendTxBuffer();
  u8state = COM_WAITING;
  return 0;
}

int8_t Modbus::poll() {
  // check if there is any incoming frame
  uint8_t u8current = port->available();

  if (millis() > u32timeOut) {
    u8state = COM_IDLE;
    u16errCnt++;
    return 0;
  }

  if (u8current == 0) return 0;

  // check T35 after frame end or still no frame end
  if (u8current != u8lastRec) {
    u8lastRec = u8current;
    u32time = millis() + T35;
    return 0;
  }
  if (millis() < u32time) return 0;

  // transfer Serial buffer frame to auBuffer
  u8lastRec = 0;
  int8_t i8state = getRxBuffer();
  if (i8state < 7) {
    u8state = COM_IDLE;
    u16errCnt++;
    return i8state;
  }

  // validate message: id, CRC, FCT, exception
  uint8_t u8exception = validateAnswer();
  if (u8exception != 0) {
    u8state = COM_IDLE;
    return u8exception;
  }

  // process answer
  switch ( au8Buffer[ FUNC ] ) {
  case MB_FC_READ_COILS:
  case MB_FC_READ_DISCRETE_INPUT:
    // call get_FC1 to transfer the incoming message to au16regs buffer
   // get_FC1( );
    break;
  case MB_FC_READ_INPUT_REGISTER:
  case MB_FC_READ_REGISTERS :
    // call get_FC3 to transfer the incoming message to au16regs buffer
    get_FC3( );
    break;
  case MB_FC_WRITE_COIL:
  case MB_FC_WRITE_REGISTER :
  case MB_FC_WRITE_MULTIPLE_COILS:
  case MB_FC_WRITE_MULTIPLE_REGISTERS :
    // nothing to do
    break;
  default:
    break;
  }
  u8state = COM_IDLE;
  return u8BufferSize;
}

int8_t Modbus::poll( uint16_t *regs, uint8_t u8size ) {

  au16regs = regs;
  u8regsize = u8size;

  // check if there is any incoming frame
  uint8_t u8current = port->available();
  if (u8current == 0) return 0;

  // check T35 after frame end or still no frame end
  if (u8current != u8lastRec) {
    u8lastRec = u8current;
    u32time = millis() + T35;
    return 0;
  }
  if (millis() < u32time) return 0;

  u8lastRec = 0;
  int8_t i8state = getRxBuffer();
  if (i8state < 7) return i8state;

  // check slave id
  if (au8Buffer[ ID ] != u8id) return 0;

  // validate message: CRC, FCT, address and size
  uint8_t u8exception = validateRequest();
  if (u8exception > 0) {
    if (u8exception != NO_REPLY) {
      buildException( u8exception );
      sendTxBuffer();
    }
    return u8exception;
  }

  u32timeOut = millis() + long(u16timeOut);

  // process message
  switch ( au8Buffer[ FUNC ] ) {
  case MB_FC_READ_COILS:
  case MB_FC_READ_DISCRETE_INPUT:
    return process_FC1( regs, u8size );
    break;
  case MB_FC_READ_INPUT_REGISTER:
  case MB_FC_READ_REGISTERS :
    return process_FC3( regs, u8size );
    break;
  case MB_FC_WRITE_COIL:
    return process_FC5( regs, u8size );
    break;
  case MB_FC_WRITE_REGISTER :
    return process_FC6( regs, u8size );
    break;
  case MB_FC_WRITE_MULTIPLE_COILS:
    return process_FC15( regs, u8size );
    break;
  case MB_FC_WRITE_MULTIPLE_REGISTERS :
    return process_FC16( regs, u8size );
    break;
  default:
    break;
  }
}

void Modbus::init(uint8_t u8id, uint8_t u8serno, uint8_t u8txenpin) {
  this->u8id = u8id;
  this->u8serno = (u8serno > 3) ? 0 : u8serno;
  this->u8txenpin = u8txenpin;
  this->u16timeOut = 1000;// intially set for 1000
}

int8_t Modbus::getRxBuffer() {
  boolean bBuffOverflow = false;

  if (u8txenpin > 1) digitalWrite( u8txenpin, LOW );

  u8BufferSize = 0;
  while ( port->available() ) {
    au8Buffer[ u8BufferSize ] = port->read();
    u8BufferSize ++;

    if (u8BufferSize >= MAX_BUFFER) bBuffOverflow = true;
  }
  u16InCnt++;

  if (bBuffOverflow) {
    u16errCnt++;
    return ERR_BUFF_OVERFLOW;
  }
  u32timeOut=500;
   // u32timeOut = millis() + (unsigned long) u16timeOut;
  return u8BufferSize;
}

void Modbus::sendTxBuffer() {
  uint8_t i = 0;

  // append CRC to message
  uint16_t u16crc = calcCRC( u8BufferSize );
  au8Buffer[ u8BufferSize ] = u16crc >> 8;
  u8BufferSize++;
  au8Buffer[ u8BufferSize ] = u16crc & 0x00ff;
  u8BufferSize++;

  // set RS485 transceiver to transmit mode
  if (u8txenpin > 1) {
    switch ( u8serno ) {
#if defined(UBRR1H)
    case 1:
      UCSR1A = UCSR1A | (1 << TXC1);
      break;
#endif

#if defined(UBRR2H)
    case 2:
      UCSR2A = UCSR2A | (1 << TXC2);
      break;
#endif

#if defined(UBRR3H)
    case 3:
      UCSR3A = UCSR3A | (1 << TXC3);
      break;
#endif
    case 0:
    default:
      UCSR0A = UCSR0A | (1 << TXC0);
      break;
    }
    digitalWrite( u8txenpin, HIGH );
  }

  // transfer buffer to serial line
  port->write( au8Buffer, u8BufferSize );

  // keep RS485 transceiver in transmit mode as long as sending
  if (u8txenpin > 1) {
    switch ( u8serno ) {
#if defined(UBRR1H)
    case 1:
      while (!(UCSR1A & (1 << TXC1)));
      break;
#endif

#if defined(UBRR2H)
    case 2:
      while (!(UCSR2A & (1 << TXC2)));
      break;
#endif

#if defined(UBRR3H)
    case 3:
      while (!(UCSR3A & (1 << TXC3)));
      break;
#endif
    case 0:
    default:
      while (!(UCSR0A & (1 << TXC0)));
      break;
    }

    // return RS485 transceiver to receive mode
    digitalWrite( u8txenpin, LOW );
  }
  port->flush();
  u8BufferSize = 0;

  // set time-out for master
//  u32timeOut = millis() + (unsigned long) u16timeOut;
 u32timeOut=500;
  // increase message counter
  u16OutCnt++;
}

uint16_t Modbus::calcCRC(uint8_t u8length) {
  unsigned int temp, temp2, flag;
  temp = 0xFFFF;
  for (unsigned char i = 0; i < u8length; i++) {
    temp = temp ^ au8Buffer[i];
    for (unsigned char j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp >>= 1;
      if (flag)
        temp ^= 0xA001;
    }
  }
  // Reverse byte order.
  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;
  // the returned value is already swapped
  // crcLo byte is first & crcHi byte is last
  return temp;
}

uint8_t Modbus::validateRequest() {
  // check message crc vs calculated crc
  uint16_t u16MsgCRC =
    ((au8Buffer[u8BufferSize - 2] << 8)
    | au8Buffer[u8BufferSize - 1]); // combine the crc Low & High bytes
  if ( calcCRC( u8BufferSize - 2 ) != u16MsgCRC ) {
    u16errCnt ++;
    return NO_REPLY;
  }

  // check fct code
  boolean isSupported = false;
  for (uint8_t i = 0; i < sizeof( fctsupported ); i++) {
    if (fctsupported[i] == au8Buffer[FUNC]) {
      isSupported = 1;
      break;
    }
  }
  if (!isSupported) {
    u16errCnt ++;
    return EXC_FUNC_CODE;
  }

  // check start address & nb range
 // uint16_t u16regs = 4000;
 uint16_t u16regs = 0;
  uint8_t u8regs;
  switch ( au8Buffer[ FUNC ] ) {
  case MB_FC_READ_COILS:
  case MB_FC_READ_DISCRETE_INPUT:
  case MB_FC_WRITE_MULTIPLE_COILS:
    u16regs = word( au8Buffer[ ADD_HI ], au8Buffer[ ADD_LO ]) / 16;
    u16regs += word( au8Buffer[ NB_HI ], au8Buffer[ NB_LO ]) / 16;
    u8regs = (uint8_t) u16regs;
    if (u8regs > u8regsize) return EXC_ADDR_RANGE;
    break;
  case MB_FC_WRITE_COIL:
    u16regs = word( au8Buffer[ ADD_HI ], au8Buffer[ ADD_LO ]) / 16;
    u8regs = (uint8_t) u16regs;
    if (u8regs > u8regsize) return EXC_ADDR_RANGE;
    break;
  case MB_FC_WRITE_REGISTER :
    u16regs = word( au8Buffer[ ADD_HI ], au8Buffer[ ADD_LO ]);
    u8regs = (uint8_t) u16regs;
    if (u8regs > u8regsize) return EXC_ADDR_RANGE;
    break;
  case MB_FC_READ_REGISTERS :
  case MB_FC_READ_INPUT_REGISTER :
  case MB_FC_WRITE_MULTIPLE_REGISTERS :
    u16regs = word( au8Buffer[ ADD_HI ], au8Buffer[ ADD_LO ]);
    u16regs += word( au8Buffer[ NB_HI ], au8Buffer[ NB_LO ]);
    u8regs = (uint8_t) u16regs;
    if (u8regs > u8regsize) return EXC_ADDR_RANGE;
    break;
  }
  return 0; // OK, no exception code thrown
}

uint8_t Modbus::validateAnswer() {
  // check message crc vs calculated crc
  uint16_t u16MsgCRC =
    ((au8Buffer[u8BufferSize - 2] << 8)
    | au8Buffer[u8BufferSize - 1]); // combine the crc Low & High bytes
  if ( calcCRC( u8BufferSize - 2 ) != u16MsgCRC ) {
    u16errCnt ++;
    return NO_REPLY;
  }

  // check exception
  if ((au8Buffer[ FUNC ] & 0x80) != 0) {
    u16errCnt ++;
    return ERR_EXCEPTION;
  }

  // check fct code
  boolean isSupported = false;
  for (uint8_t i = 0; i < sizeof( fctsupported ); i++) {
    if (fctsupported[i] == au8Buffer[FUNC]) {
      isSupported = 1;
      break;
    }
  }
  if (!isSupported) {
    u16errCnt ++;
    return EXC_FUNC_CODE;
  }

  return 0; // OK, no exception code thrown
}

void Modbus::buildException( uint8_t u8exception ) {
  uint8_t u8func = au8Buffer[ FUNC ];  // get the original FUNC code

  au8Buffer[ ID ]      = u8id;
  au8Buffer[ FUNC ]    = u8func + 0x80;
  au8Buffer[ 2 ]       = u8exception;
  u8BufferSize         = EXCEPTION_SIZE;
}

The functionality Check
void Modbus::get_FC3() {
  uint8_t u8byte, i;
  u8byte = 3;

  for (i = 0; i < au8Buffer[ 2 ] / 2; i++) {
    au16regs[ i ] = word(
    au8Buffer[ u8byte ],
    au8Buffer[ u8byte + 1 ]);
    u8byte += 2;
  }
}

int8_t Modbus::process_FC1( uint16_t *regs, uint8_t u8size ) {
  uint8_t u8currentRegister, u8currentBit, u8bytesno, u8bitsno;
  uint8_t u8CopyBufferSize;
  uint16_t u16currentCoil, u16coil;

  // get the first and last coil from the message
  uint16_t u16StartCoil = word( au8Buffer[ ADD_HI ], au8Buffer[ ADD_LO ] );
  uint16_t u16Coilno = word( au8Buffer[ NB_HI ], au8Buffer[ NB_LO ] );

  // put the number of bytes in the outcoming message
  u8bytesno = (uint8_t) (u16Coilno / 8);
  if (u16Coilno % 8 != 0) u8bytesno ++;
  au8Buffer[ ADD_HI ]  = u8bytesno;
  u8BufferSize         = ADD_LO;

  // read each coil from the register map and put its value inside the outcoming message
  u8bitsno = 0;

  for (u16currentCoil = 0; u16currentCoil < u16Coilno; u16currentCoil++) {
    u16coil = u16StartCoil + u16currentCoil;
    u8currentRegister = (uint8_t) (u16coil / 16);
    u8currentBit = (uint8_t) (u16coil % 16);

    bitWrite(
    au8Buffer[ u8BufferSize ],
    u8bitsno,
    bitRead( regs[ u8currentRegister ], u8currentBit ) );
    u8bitsno ++;

    if (u8bitsno > 7) {
      u8bitsno = 0;
      u8BufferSize++;
    }
  }

  // send outcoming message
  if (u16Coilno % 8 != 0) u8BufferSize ++;
  u8CopyBufferSize = u8BufferSize +2;
  sendTxBuffer();
  return u8CopyBufferSize;
}

int8_t Modbus::process_FC3( uint16_t *regs, uint8_t u8size ) {

  uint8_t u8StartAdd = word( au8Buffer[ ADD_HI ], au8Buffer[ ADD_LO ] );
  uint8_t u8regsno = word( au8Buffer[ NB_HI ], au8Buffer[ NB_LO ] );
  uint8_t u8CopyBufferSize;
  uint8_t i;

  au8Buffer[ 2 ]       = u8regsno * 2;
  u8BufferSize         = 3;

  for (i = u8StartAdd; i < u8StartAdd + u8regsno; i++) {
    au8Buffer[ u8BufferSize ] = highByte(regs[i]);
    u8BufferSize++;
    au8Buffer[ u8BufferSize ] = lowByte(regs[i]);
    u8BufferSize++;
  }
  u8CopyBufferSize = u8BufferSize +2;
  sendTxBuffer();

  return u8CopyBufferSize;
}

int8_t Modbus::process_FC5( uint16_t *regs, uint8_t u8size ) {
  uint8_t u8currentRegister, u8currentBit;
  uint8_t u8CopyBufferSize;
  uint16_t u16coil = word( au8Buffer[ ADD_HI ], au8Buffer[ ADD_LO ] );

  // point to the register and its bit
  u8currentRegister = (uint8_t) (u16coil / 16);
  u8currentBit = (uint8_t) (u16coil % 16);

  // write to coil
  bitWrite(
  regs[ u8currentRegister ],
  u8currentBit,
  au8Buffer[ NB_HI ] == 0xff );

  // send answer to master
  u8BufferSize = 6;
  u8CopyBufferSize = u8BufferSize +2;
  sendTxBuffer();

  return u8CopyBufferSize;

}

int8_t Modbus::process_FC6( uint16_t *regs, uint8_t u8size ) {

  uint8_t u8add = word( au8Buffer[ ADD_HI ], au8Buffer[ ADD_LO ] );
  uint8_t u8CopyBufferSize;
  uint16_t u16val = word( au8Buffer[ NB_HI ], au8Buffer[ NB_LO ] );

  regs[ u8add ] = u16val;

  // keep the same header
  u8BufferSize         = RESPONSE_SIZE;

  u8CopyBufferSize = u8BufferSize +2;
  sendTxBuffer();

  return u8CopyBufferSize;
}

int8_t Modbus::process_FC15( uint16_t *regs, uint8_t u8size ) {
  uint8_t u8currentRegister, u8currentBit, u8frameByte, u8bitsno;
  uint8_t u8CopyBufferSize;
  uint16_t u16currentCoil, u16coil;
  boolean bTemp;

  // get the first and last coil from the message
  uint16_t u16StartCoil = word( au8Buffer[ ADD_HI ], au8Buffer[ ADD_LO ] );
  uint16_t u16Coilno = word( au8Buffer[ NB_HI ], au8Buffer[ NB_LO ] );

  // read each coil from the register map and put its value inside the outcoming message
  u8bitsno = 0;
  u8frameByte = 7;
  for (u16currentCoil = 0; u16currentCoil < u16Coilno; u16currentCoil++) {

    u16coil = u16StartCoil + u16currentCoil;
    u8currentRegister = (uint8_t) (u16coil / 16);
    u8currentBit = (uint8_t) (u16coil % 16);

    bTemp = bitRead(
    au8Buffer[ u8frameByte ],
    u8bitsno );

    bitWrite(
    regs[ u8currentRegister ],
    u8currentBit,
    bTemp );

    u8bitsno ++;

    if (u8bitsno > 7) {
      u8bitsno = 0;
      u8frameByte++;
    }
  }

  // send outcoming message
  // it's just a copy of the incomping frame until 6th byte
  u8BufferSize         = 6;
  u8CopyBufferSize = u8BufferSize +2;
  sendTxBuffer();
  return u8CopyBufferSize;
}

int8_t Modbus::process_FC16( uint16_t *regs, uint8_t u8size ) {
  uint8_t u8func = au8Buffer[ FUNC ];  // get the original FUNC code
  uint8_t u8StartAdd = au8Buffer[ ADD_HI ] << 8 | au8Buffer[ ADD_LO ];
  uint8_t u8regsno = au8Buffer[ NB_HI ] << 8 | au8Buffer[ NB_LO ];
  uint8_t u8CopyBufferSize;
  uint8_t i;
  uint16_t temp;

  // build header
  au8Buffer[ NB_HI ]   = 0;
  au8Buffer[ NB_LO ]   = u8regsno;
  u8BufferSize         = RESPONSE_SIZE;

  // write registers
  for (i = 0; i < u8regsno; i++) {
    temp = word(
    au8Buffer[ (BYTE_CNT + 1) + i * 2 ],
    au8Buffer[ (BYTE_CNT + 2) + i * 2 ]);

    regs[ u8StartAdd + i ] = temp;
  }
  u8CopyBufferSize = u8BufferSize +2;
  sendTxBuffer();

  return u8CopyBufferSize;
}

several suggestions:  1) separate the code to write to the modbus from the code to read the modbus 2) use something like select() or poll() after writing to the modbus, then call the function to read the modbus. 3) modbus does not initiate communication, it only responds to commands (there are several different commands and your code does not allow for each command having variations in the format. )  4) the length of each command and response message can (and usually is) different.  5) do not send useless bytes (all those zeros).  5) (cont)

all modbus communication is a) command/request b) response.  Your code is not allowing for that

suggest setting up each command/request from separate functions and each of those separate functions call a serial write function, then select() then a serial read function.  During the read, need to check the device id to determine if response is to be ignored or not. Then check the response type to determine what to do (it may be an error response) then check the length to determine how many bytes still to read,  then read the data bytes and CRC, Then check the CRC to determine the validity of the message.

@user3629249 is there any example code written in C , to get send command and get response.The above code written in Embedded c . is there already code written for Atmega 328 or modbus functions.

The newly posted edit, the C++ code, can be changed to C by replacing all the Modbus:: sequences with modbus_.   I did not note any other items that are specific to C++, however, the C++ code is assuming several definitions and structs are already setup, and available.

the use of the type: boolean means you will need the statement: #include <stdbool.h>

for ease of readability of the C++ code, 1) suggest the width of an indent be 4 spaces rather than just 2 spaces 2) separate the code blocks (for, if, else, while, do...while, switch, case, default) via a blank line.  3) the file name extension needs to be changed from cpp to c

@user3629249 Is there any code already written in C for mODBUS RTU

this may be of some help: http://cboard.cprogramming.com/networking-device-communication/149507-modbus-rtu-c-programming.html for some code and here is the home web site for modbus: http://www.modbus.org/tech.php and here us some more sample code: http://control.com/thread/1301963718


text:
Relay activation
I am posting my simple code here, I wanted to print the Output_Current Inspite when delay function called.Below is my code.
#include <MsTimer2.h>

int Analog_Pin=5;
int newaverage;
float Output_Current;
#define RELAY1  7
#define MAX_TRIP_COUNT  5
float Current_Limit=0.6;
static int Trip_Count=0;
static int Tripped_Flag=1;
int Serial_Status=0;

void TakeReading()
{
  newaverage = analogRead(A5);

//  Serial.print("newaverage:");
  //Serial.println(newaverage);
  Output_Current = 0.0336666666667*newaverage - 17.17;
}

void Chk_Relay_Tripped()
{
  if(Output_Current>=Current_Limit)
  {
    Trip_Count=Trip_Count+1;
    if((Trip_Count>=MAX_TRIP_COUNT) &&(Serial_Status==0))
    {

      Trip_Count=0;

  MsTimer2::set(30000, Relay_Activate); // 500ms period
  MsTimer2::start();
     // Relay_Activate();
    }
    else
      if(Serial_Status==1)
      {
        Serial.println("> MODE");
        Relay_Deactivate();
      }

  }
  else
  {
    Trip_Count=Trip_Count-1;
    if(Trip_Count<0)
    {
      Trip_Count=0;
    }

    if(Trip_Count<MAX_TRIP_COUNT && Serial_Status==1)
    {
      Relay_Deactivate();
      Serial_Status=0;
    }

  }

}

void Relay_Activate()
{
   // MsTimer2::stop();

   for (unsigned long start = millis(); millis() - start < 10000;)
  {
    digitalWrite(RELAY1,HIGH);
    Serial_Status=1;
  }

    digitalWrite(RELAY1,HIGH);
    Serial_Status=1;

}

void  Relay_Deactivate()
{
  digitalWrite(RELAY1,LOW);
 // Serial_Status=0;
}

void Relay_Intialize()
{
  digitalWrite(RELAY1,LOW);
}

void setup() {
  Serial.begin(9600); // set serial speed
  pinMode(RELAY1, OUTPUT); // set LED as output
  //digitalWrite(RELAY1, LOW); //turn off LED

  pinMode(Analog_Pin,INPUT);
  Relay_Intialize();
}

void loop(){
  TakeReading();
  Chk_Relay_Tripped();
  Serial.println(Output_Current);
   //while (Serial.available() == 0); // do nothing if nothing sent
  int val = Serial.read() - '0';
  if (val == 1) { // test for command 1 then turn on LED
    Serial.println("RELAY on");
    digitalWrite(RELAY1, LOW); // turn on LED
    Serial_Status=1;

  }
  else if (val == 0) // test for command 0 then turn off LED
  {
    Serial.println("RELAY OFF");
    digitalWrite(RELAY1, HIGH); // turn off LED
    Serial_Status=0;
  }
  delay(500);
}

In above code everything working fine. But as soon as this function called . It wait 30s. after that it will print data. But i wanted to print data on serial monitor even if this function called. Please let me know how can i do this. Main intenstion of code is when current >1A trip the relay , wait for 30S and connect back. I wanted to print output even in 30S
void Relay_Activate()
{

   for (unsigned long start = millis(); millis() - start < 30000;)
  {
    digitalWrite(RELAY1,HIGH);
    Serial_Status=1;
  }

}

I totally don't understand what you're trying to achieve. Reading the code doesn't make it any clearer. A better description would be helpful.

@Gerben this code clarify it. I wanted to print all data within 30S delay

I read you code as: check the output current every 500ms. If it exceeds the limit more than MAX_TRIP_COUNT times, set Relay_Activate to run after 30secs. In Relay_Activate, write HIGH to the RELAY1 over and over for 30 seconds:
void Relay_Activate()
{
  for (unsigned long start = millis(); millis() - start < 30000;)
  {
    digitalWrite(RELAY1,HIGH);
    Serial_Status=1;
  }
}

I don't think you really mean to do this, especially as after the 30 seconds you are not writing LOW to turn it off. Maybe you mean that after 30 seconds it should start checking the current again?
void Relay_Activate()
{
  digitalWrite(RELAY1,HIGH);
  Serial_Status=1;
}

What you want is a state machine so that your delays don't hold up your loop. Here is some pseudo code:
loop {

* read current
* print out current

switch(current_state) {
  //Normal operation
  case 0:
    * check if tripped
      - if tripped change state to 1
  //Turn on relay
  case 1:
    * turn on relay
    * set state_timer = millis()
    * change state to 2
  //Turn of relay after 30 seconds
  case 2:
    * if millis() -state_timer > 30000 turn off relay
    * change state to 0
}
delay 500ms
}

So post your updated code along with an explanation of what you did, and accept it as the answer to your question. That way your question becomes a way for others to learn.


text:
Arduino and visual basic Serial data
I am trying to send command serially through Vb.through serial monitor working fine . But Through VB it not detecting port
My arduino code:
int ledPin = 2; // the number of the LED pin

void setup() {
Serial.begin(9600); // set serial speed
pinMode(ledPin, OUTPUT); // set LED as output
digitalWrite(ledPin, LOW); //turn off LED
}

void loop(){
while (Serial.available() == 0); // do nothing if nothing sent
int val = Serial.read() - '0'; // deduct ascii value of '0' to find numeric value of sent number

if (val == 1) { // test for command 1 then turn on LED
Serial.println("LED on");
digitalWrite(ledPin, HIGH); // turn on LED
}
else if (val == 0) // test for command 0 then turn off LED
{
Serial.println("LED OFF");
digitalWrite(ledPin, LOW); // turn off LED
}
else // if not one of above command, do nothing
{
//val = val;
Serial.println("Wrong command");
}
Serial.println(val);
Serial.flush(); // clear serial port
}

VB Code
Imports System.IO
Imports System.IO.Ports
Imports System.Threading

Public Class Form1
    Shared _continue As Boolean

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        SerialPort1.Open()
        SerialPort1.PortName = "COM3"

        SerialPort1.BaudRate = 9600
        SerialPort1.DataBits = 8
        SerialPort1.Parity = IO.Ports.Parity.None
        SerialPort1.StopBits = IO.Ports.StopBits.One
        SerialPort1.Handshake = IO.Ports.Handshake.None
        SerialPort1.Encoding = System.Text.Encoding.Default 'very important!

    End Sub

    Private Sub Button1_Click_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1_Click.Click
        SerialPort1.Open()
        SerialPort1.Write("1")
        SerialPort1.Close()
    End Sub

    Private Sub Button2_Click_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2_Click.Click
        SerialPort1.Open()
        SerialPort1.Write("0")
        SerialPort1.Close()
    End Sub

End Class

Error I am getting .Arduino port is 3. and configured to port 3 . i dont know why it giving error.
The port 'com10' does not exist.

This Line added as you said
Private Sub Current_Read_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        SerialPort1.Open()
        Dim str As String
        str = SerialPort1.ReadExisting
        Current_Read.Text = str
        SerialPort1.Close()
    End Sub

This is working But data not being updating
Private Sub Current_Read_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Current_Read.Text =SerialPort1.ReadLine
    End Sub

You've opened the port before you've configured it.

I removed already those line same error.

@AMPS which lines have you removed exactly? Cn you edit your post to show the modified code that still does not work?

Private Sub Current_Read_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
SerialPort1.Open()
Dim str As String
str = SerialPort1.ReadChar
Current_Read.Text = str
SerialPort1.Close()
End Sub


text:
Bluetooth OBD2 ELM327 connectivity issues
I made a little project using an Arduino UNO, a 3.5" display, a HC-05 bluetooth module and an ELM327 (cheap ebay clone). I managed to establish communication, read the data, interpret and display it, but only one problem remains that keeps bothering me.
After some exchanges of data between Arduino and the OBD2 adapter, communication just drops.  I don't know if its from the HC-05 or ELM327. As far as I could debug it, the data from ELM327 comes incomplete. Usually the response from it, transformed into chars, is like "0103141 03 02 00 >" and I use the ">" char in the program as data exchange complete. When the problem occurs I receive fewer bytes from the OBD adapter and without the ">" char, something like "0103141 03 ".
I made a function that resets the HC-05 module and reconnects, but it takes a few seconds and I want my data to come as a continuous flow.
I tried a few methods of debugging, such as changing baud rate of the HC-05, and adding some delays, but I haven't come to a solution.
I believe that the problem might me one of these three:

The cheap ebay clone messing things up.
The HC-05 not sending the complete data.
A problem with my code.

Below I have attached the part of the code that does the sending of the command and reading the response. When the problem occurs, it gets stuck in the while loop because I have no terminating ">" char and I have to break it, call another function that re-establishes communication and so on.
So my question is: has anyone confronted this problem where ELM327 sends incomplete data that cannot be used?
 BTSerial.println("010F1");
 BTSerial.flush();
 delay(10);
  if (BTSerial.available()>0)
      busy = true;
  while(busy = true && inData != 62)
  {
      temp++;
      if (temp>500000){
          resetBT();
          BTSerial.println("ATWS");
          break;
      }
      if (BTSerial.available()>0){
          inData=0;
          inData = BTSerial.read();
          if(inData != 32) {
              buf[i] = inData;
              Serial.print(char(buf[i]));
              i++;
          }

      }

  }
Serial.println();
busy=false;
inData = 0;
i = 0;
memset(buf, 0, sizeof(buf));
temp = 0;

reduce your code to bare minimum ..... remove the whole while loop and just dump the received data to the terminal window .... analyze the data .... there may be something that you are overlooking ..... post the data into your question, if there is not way too much of it .... maybe some pattern may be found

I managed to solve the issue. After some more testing, I ended up noticing that the problem was somehow the data exchange through the HC-05 bluetooth module. I changed it from being via SoftwareSerial library to the main serial com port and I had no issues since then. I don't know how that library may have caused the problem, but that was it.

You can much more easily interface your Arduino with an ELM327 in software with the library ELMduino.h. It's downloadable through the Arduino IDE and includes examples.


text:
Linear actuator jitters/vibrates when getting PWM from Arduino Mega 2560 through JKR 21v3 motor controller
I recently bought this linear actuator and motor controller from Pololu:

Linear actuator
Motor Controller JRK21v3

There are several steps that I have to follow in order to set this thing up before I can test it. These instructions can be found here: Pololu JRK USB Motor Controller User’s Guide » Setting Up Your System
I would like to program this using PWM method because I would like to keep the Serial RX for other sensors.  From my little experiment, by using a potentiometer, I noticed this pattern:
Position: Voltage

Fully extended : 0 V
At Rest : 2.35V
Fully Retracted  : 4.77V.

For this system, I will be controlling it using a PS2 controller. So, by using only the Y_axis of the analog joystick of a PS2 Controller (Up: 0, Rest: 128 and Down: 255), I program it as follows:
//Move Linear Actuator with PS2 on JRK21v3 Controller

#define pwm 6           //red wire
#define dir 7           //yellow wire

//PS2 controller
#include <SoftwareSerial.h>
#include <Cytron_PS2Shield.h>

Cytron_PS2Shield ps2(10, 11); // SoftwareSerial: Rx and Tx pin

void setup()
{
  pinMode(pwm,OUTPUT);

  ps2.begin(9600);
  Serial.begin(9600);
}

void loop()
{
  int Y_axis = ps2.readButton(PS2_JOYSTICK_RIGHT_Y_AXIS);  // 0 - 255
  Serial.print("Y_axis:");
  Serial.println(Y_axis);

  analogWrite(pwm, Y_axis);
}

When I tested it, the linear actuator jitters/vibrates when it is at rest position. What could possibly cause this? Is it the duty cycle due to the PWM? How can I fix this or are there any other better methods?

The Pololu jrk 21v3 motor controller supports four input modalities: via USB, via TTL-level serial, via RC / pulse width control, and via the mode you are trying to use, an analog 0-5V input.
It appears you are trying to use a PWM output to produce an analog signal control mode.  A PWM signal is a pulsed digital output rather than an analog signal.  The 21v3 may be jittering its control setpoint back and forth between 0V and 5V at a high frequency, which will make the linear actuator jitter.
Try adding an RC low-pass filter to the PWM output, ie between your PWM pin 6 and the input to the 21v3.  (Note, it might make more sense to use a software-serial output to control the 21v3, instead of using a PWM output with a low-pass filter, which may still allow use of hardware serial for your other sensors...)
To verify if an RC filter will work, try at first with large R (eg 5KΩ to 10KΩ) and large C (eg 5μF to 10μF) to see if the jitter goes away.  If so, you then can tune the filter to find how small you can make R or C and still avoid jitter.  A filter with smaller RC will allow higher-frequency control than will one with larger RC, but may be more prone to jitter.  R should be somewhat less than the input impedance of the 21v3's analog input.  To determine that value, look at the data sheet of whatever chip that input goes into.

Thanks. Yes, I agree that the motor jitters since PWM is a pulsed type signal. But how is that different from the controlling it via the serial pin RX, TX? Aren't the signals from those pins in digital form too instead of analog? That would cause the motor to jitter too right? I dont think arduino outputs analog signal, am I right?

True, most Arduino devices don't output analog signals.  (Due and Teensy, perhaps others, have some DAC outputs.)   ¶ The Pololu Jrk 21v3 has a processor on it.  When that processor receives motor speed setpoint information via USB or serial it controls an attached DC motor to that speed.  When it gets a hobby-RC pulse train it measures the duty cycle and proportionally controls an attached DC motor.    When it gets an analog voltage level it  measures the voltage and proportionally controls an attached DC motor.   When it gets PWM that you've called analog it controls speed erratically.

The jitter would not be from the frame rate of the pwm on the actiator but from the sampling effects of the driver reading a pwm signal (rather than an analog one) at uncoordinated instants in time.  Try servo pwm mode.

I got this working using the Servo library.

You set the input method to PWM.
Connect your RX on the motor controller and hook it up to the servo pin.
Connect the ground of the Arduino to the ground of the JRK 21v3.
Then use the knob servo sample by hooking up a pot to a Arduino.
The calibrate the JRK 21v3 by selecting learn.

Now you can use the actuator as a servo.


text:
Rate of serial communication (UART) of a sensor is faster than speed of processing of microcontroller
I have a Vector Nav VN100 IMU sensor that sends data serially UART. I have interfaced it with ATmega32. It receives data (ROLL angel) from the sensor and according to the ROLL angel, it controls a servo motor.
My question, if the sending rate is faster than processing speed of the ATmega32, then  some data from the sensor will be dropped. How to overcome this problem?

If the data is coming faster, that it can be processed and you cannot change the rate, you have to drop data or use a faster board

@chrisl Is not there any other way such as using  buffer instead of dropping data?

Even if you use a buffer. When it is full you need to drop data. What are your exact requirements? Reading data contineously? Or just for a limited time period?

@chrisl just for a limited time

What is your incoming data rate? That is what baud rate will you be using? How frequently will the "roll angle" be sent? And how big is each message (in bytes)?

@GMc Baudrate is 921600

There were three questions there... how frequently will messages be sent? And how long is each message in bytes? If the baud rate is 921600 but you only receive 1 message per second that is just 2 bytes long and you are using a UART (for example) then probably the answer is "you will be ok". On the other hand if there is a continuous sustained stream of data at that baud rate with no pause in between messages then probably the answer is "you have no chance". There are multiple factors that determine the answer to your question.

When using an embedded processor's hardware implemented UART, it is often the case that the rate at which the software processes the data is a fraction of the Gross bit rate some times referred to as the Baud rate.  If the UART is configured to handle 8 bit RS-232 where the Gross bit rate is 10000 bits per second, the processor only has to handle data at a faction of that rate.  Perhaps 1/10 given several bits of over head and space between characters.
Processor intervention can be further reduced if the hardware UART contains several bytes of buffering.  For every doubling of the number of hardware supported bytes of buffering, processor interventions events are cut in half.
Beyond this, there are embedded processors in which the UART supports DMA or Direct Memory Accessing.  This is where the hardware UART will write the received data directly into the processor's memory with out need of processor intervention.  This feature is usually only found on feature rich embedded processors.
Study this PDF to understand the abilities and limitations of the ATmega32 processor.  Specifically the USART section starting on page 140.


text:
If an Arduino goes to sleep, does the attached ESP also sleep?
I am using Arduino Uno + an attached ESP-01 (ESP8266).
I want to save battery, so I made my Arduino get sleep & interrupt by a watchdog timer.
But if the Arduino goes to sleep, does the attached ESP also sleep?

you have to put the ESP8266 to sleep


text:
Random lighting for 18 pin LED
I am trying to write code so that 18 LEDs will light up randomly except 2 of them light up together. Am I using random wrong? I initialized it to make the random number random.
Here is my code:
int timer = 1000;

int ranndom;

void setup() {
    // put your setup code here, to run once:
    pinMode(30, OUTPUT);
    pinMode(31, OUTPUT);
    pinMode(32, OUTPUT);
    pinMode(33, OUTPUT);
    pinMode(34, OUTPUT);
    pinMode(35, OUTPUT);
    pinMode(36, OUTPUT);
    pinMode(37, OUTPUT);
    pinMode(38, OUTPUT);
    pinMode(39, OUTPUT);
    pinMode(40, OUTPUT);
    pinMode(41, OUTPUT);
    pinMode(42, OUTPUT);
    pinMode(43, OUTPUT);
    pinMode(44, OUTPUT);
    pinMode(45, OUTPUT);
    pinMode(46, OUTPUT);
    pinMode(47, OUTPUT);

}

void loop() {
    // put your main code here, to run repeatedly:

    ranndom = random(30, 47);

    if (ranndom == 38 || ranndom == 39) {
        digitalWrite(38, HIGH);
        digitalWrite(39, HIGH);
        delay(timer);

        digitalWrite(38, LOW);
        digitalWrite(39, LOW);
        delay(timer);
    }
    else {
        digitalWrite(ranndom, HIGH);
        delay(timer);

        digitalWrite(ranndom, LOW);
        delay(timer);
    }

}

And what is the problem with this code? Is it not working as you intended? If yes, please describe how it behaves and what you expected to do.

It just lights up the lights but does not turn them off. Is the code correct? like was random used correctly?

is the format correct? is the code used correctly?

pin 47 will not light up ever, because the maximum value parameter of random() is exclusive. And you might want to use randomSeed() to get real random numbers (the current way the number row will be equal for every power on of the device). The code itself seems good and should work.

So by changing random() to randomSeed(30,47) It will include 47 and get random numbers that associate with the pin the LED is connected to?

No, randomSeed has another functionality. Please read the documentation for it. And to get 47 into it, you need to specify a maximum value of 48.

when I change it, is it giving me the error of too many arguments. What do I need to change?

See here at the documentation that shows how to use random() and randomSeed()

I went back to random(30, 48) and then plugged it in and the lights are all going on at the same time and not even following the speed

Are you sure, that you uploaded the code correctly? And are the lights connected correctly? You can test with the blink example, that comes with the Arduino IDE. What type of Arduino do you use?

Please post the circuit you are using for the LEDs.

i am using relays. The type is a eledoo mega 2560

So It has started to slightly work for about 2 cylces and then it goes back to all the lights. I am the coder and not doing the circuit.

I redid the code and it works occasionally and then it stops working. here is the code:

int timer = 1000;
long randNumber;
void setup() {
// put your setup code here, to run once:
randomSeed(analogRead(30));
}
void loop() {
// put your main code here, to run repeatedly:
randNumber = random(30,48);
pinMode(randNumber,OUTPUT);
if (randNumber == 38 || randNumber == 39) {
digitalWrite(38, HIGH);
digitalWrite(39, HIGH);
delay(timer);
digitalWrite(38, LOW);
digitalWrite(39, LOW);
}
else {
digitalWrite(randNumber, HIGH);
delay(timer);
digitalWrite(randNumber, LOW);
}
}

It would be best if you improved your question by editing your question to answer what people are asking here in the comments.

Since you are using relay: Do you have complete relay modules or do you connect just the relay directly to the Arduino? And how do you have them connected. This is important for the functionality of the code


text:
How to burn bootloader/program an ATMega 328P with an external crystal 8 MHz oscilator?
I need to program a ATMega328P on a breadboard, running on an external crystal at 8 MHz.
All of the guides I can find either use the arduino environment and describe a 16 MHz config, or using the 8 MHz internal oscillator - which is too inaccurate for this project.
How do I do this?  Configure the chip to run at 8 MHz and upload the program?

why don't you use the internal 8Mhz crystal?

Because I'm using serial communication with another device - the internal 8Mhz crystal is only rated as accurate within 10% at 25 degrees C.  Serial communication tolerates an error of about half this.

There is no such thing as an internal 8 MHz crystal, just an 8 MHz RC oscillator.

I accept the correction that the on chip device isn't a crystal.  Doesn't change the reason I can't use it :)

you forgot to ask a question.

Edited to make question explicit.

Because you edited this in once more (and I corrected it): The unit is spelled "MHz", not "Mhz".

Solution used an arduino, but I'd happily accept (and prefer) a lower level solution.  Even so, surely that's a vote to move, not vote to close?

why don't you use the internal 8Mhz crystal? There is no "internal crystal". the internal oscillator is a rc oscillator. fairly imprecise and not as stable as a crystal oscillator.

myself as of 3 hours ago.

Get an arduino or similar, install the ArduinoISP sketch
Connect the two as described here.
Change the board to Arduino Pro or Pro Mini, Processor to 3.3V, 8Mhz, Programmer: Arduino as ISP
Hit burn bootloader button
Load up the sketch that you want on the device
Without changing anything, use "Upload using programmer"
Remove arduino, fix wiring changes required to use as programmer

Committed to Electronics Stackexchange  for posterity.  Or so I can find it when I forget next time...

authors: นีโอ แอนเดอสัน