Arduino Communication



  • Hey All,
    Is it possible to have an Arduino Mega define and continuously update the rodeostat over serial communication? Im building a PID system for hydrogen peroxide using the rodeostat. I planned on using the rodeostat to monitor the value of hydrogen peroxide then use the Mega to run the PID system (using the rodeostat as the sensor essentially), data log, and provide a user interface over a serial LCD to change set point.

    In short, how would i go about getting the rodeostat to stream the sensor data continuously?

    Any help would be much appreciated!



  • @HoughA

    Yes. The Rodeostat has two expansion headers. P13 and P14 (see the schematic)

    The P13 header is a UEXT connector which exposes Serial, SPI, and I2C buses on the teensy. Any of these could be used to send a continuous stream of data to another micro-controller. The P13 header uses a 5x2 shrouded header - so you could connect to the other microcontoller using a 10-pin ribbon cable.

    You will need to make some custom modifications to the firmware. Currently no data is sent over the any of these buses and data is no collected continuously. However, I don't think the modifications you mention would be too difficult. The firmware for the Rodeostat is available online here (see the "firmware" sub-directory). Most is the implementation is in the libraries - "firmware/libraries/potentiostat" sub-directory.



  • In the firmware, how are commands printed/written via the usb? im looking for how id change the firmware to serial.read from the arduino mega. i see i need to set the serial1 to have pins 5,6 for Tx and Rx.



  • @HoughA

    The commands are sent and received as JSON. I use the ArduinoJson library to create/parse the JSON. Haven't documented this a ton, but it is pretty easy to figure out from the python library and/or the Arduino serial monitor.

    For example if for the getVariant command you would send
    {"command":"getVariant"}

    and the response from the device would be
    {"success":true,"response":{"command":"getVariant","variant":"microAmpV0.1"}}

    Similarly for the getVersion command you would send
    {"command":"getVersion"}

    and the response would be
    {"success":true,"response":{"command":"getVersion","version":"0.0.4"}}

    To get the test name send {"command":"getTestNames"}

    The response should be
    {"success":true,"response":{"command":"getTestNames","testNames",
    ["cyclic","sinusoid","constant","squareWave","linearSweep","chronoamp","multiStep"]}}

    To get the parameters for a specific test
    {"command":"getParam","test":"cyclic"}

    The response will be something like this.
    {"success":true,"response":{"command":"getParam","test":"cyclic","param":{"quietValue":0.00000,"quietTime":0,"amplitude":1.00000,"offset":0.00000,"period":1000,"numCycles":10,"shift":0.00000}}}

    etc.

    See the potentiostat.py in the software/python/potentiostat/potentiostat sub-directory for more documentation.

    Best,
    Will



  • @Will-Dickson

    So ive been tinkering with the firmware and ive still had no luck. Ive simply been trying to have the arduino send a command over the serial and trying to use the serial monitor to see if it gets through.

    On the Teensy i mapped serial1 on pins 5 and 6 in roder to use the p14 header.
    Heres the code so far:

    #include "potentiostat.h"

    using namespace ps;

    SystemState systemState;
    char mystr[32];
    void setup()
    {
    Serial.begin(UsbSerialBaudrate);
    systemState.initialize();
    systemState.setTestTimerCallback(timerCallback);
    Serial1.setTX(5);
    Serial1.setRX(6);
    Serial1.begin(115200);

    }

    void loop()
    {
    Serial1.readBytes(mystr,32);
    Serial.println(mystr);
    systemState.processMessages();
    systemState.serviceDataBuffer();

    }

    void timerCallback()
    {
    systemState.updateTestOnTimer();
    }

    void serialEvent()
    {
    systemState.updateMessageData();
    }



  • @Will-Dickson
    So after further investigation using Device Monitoring Studios i was able to watch what was being sent from the arduino mega and what was being received by the rodeostat as well as any error messages. the device monitoring also allows the ability to create a bridge between the 2 com ports on the computer so i could simulate if they were connected.

    My first issue i found was that the Arduino was printing a string with the command and the teensy kept responding with unable to parse JSON. so i took it as the arduino needed to to be sending a JSON command rather. so after that and re checking the bridge i was actually able to get the rodeo stat to respond. I have the Arduino sending a simple set voltage to 1V for 1 sec then return to 0v for 1 sec and repeat.

    Now, im trying again to have the Arduino connected to the Serial 1 input on the Teensy and im not having the same success as before. In the firmware i even adjusted it to read from Serial1 rather than serial. this is the only thing i changed in the firm ware (other than removing the mystr info in the .ino file).

    this is what ps_message_reciever.cpp looks like now. is there anything i should be changing?

    #include "ps_message_receiver.h"
    #include <util/atomic.h>

    namespace ps
    {
    MessageReceiver::MessageReceiver()
    { }

    void MessageReceiver::reset()
    {
        overflow_ = false;
        messageCnt_ = 0;
    }
    
    
    void MessageReceiver::readData()
    {
        while(Serial1.available() > 0)
        {
            char byte = Serial1.read();
            if (!serialBuffer_.full())
            {
                serialBuffer_.push_back(byte);
                if (byte == '\n')
                {
                    messageCnt_++;
                    totalMessageCnt_++;
                }
            }
            else
            {
                overflow_ = true;
            }
        }
    }
    
    
    String MessageReceiver::next()
    {
        String message("");
        if (messageCnt_ > 0)
        {
            ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
            {   
                while (!serialBuffer_.empty())
                {
                    char byte = serialBuffer_.front();
                    serialBuffer_.pop_front();
                    if (byte == '\n')
                    {
                        break;
                    }
                    message += String(byte);
                }
                messageCnt_--;
            }
        }
        return message;
    }
    
    
    bool MessageReceiver::available() const
    {
        return (messageCnt_ > 0);
    }
    
    
    uint32_t MessageReceiver::getMessageCnt() const
    {
        return messageCnt_;
    }
    
    
    uint32_t MessageReceiver::getTotalMessageCnt() const
    {
        return totalMessageCnt_;
    }
    

    } // namespace ps



  • @HoughA Make sure to build the firmware with the "Tools -> Optimize" set to FAST (and not to FASTER which is the default). There is a bug which effects the version of ArduinoJson the project is currently using which will cause it fail (when parsing etc) when the optimize setting is set to FASTER. The newer version ArduinoJson doens't have this issue, but there is a bit of an API change so I haven't upgraded yet. So for now make sure this is set to FAST when building the potentiostat firmware.



  • @Will-Dickson Yep, i made sure of it being optimized for fast. im now just stuck at the serial communication between the two devices. i had no problem when i used a basic program between two different arduinos. Im just having problems with the Arduino and Teensy now. i triple checked to make sure the tx was connected to rx of the other and vice versa. i made sure in my arduino code that it was serial printing to serial 2 which the Rx and Tx are connected. Made sure their is a line print after each command. Am i missing something? i have a feeling ive messed up in the firmware somewhere?

    Heres the code for the arduino thats sending the command:

    #include <ArduinoJson.h>

    void setup() {

    Serial2.begin(115200);

    }

    void loop() {
    StaticJsonBuffer<200> jsonBuffer;
    JsonObject& root = jsonBuffer.createObject();
    JsonObject& root2 = jsonBuffer.createObject();

    root["command"] = "setVolt";
    root["v"] = 1;

    root.printTo(Serial2);
    Serial2.println();

    delay(1000);

    root2["command"] = "setVolt";
    root2["v"] = 0;

    root2.printTo(Serial2);
    Serial2.println();

    delay(1000);
    }



  • @HoughA

    I think the issue might be with using D3 and D4 as Tx and Rx pins for Serial1 in the the teensy 3.2. It looks like they are the Tx, Rx pins for the CAN bus not a UART .... You could use SoftwareSerial on these pins. The other option would be to move to something like I2C or SPI.



  • @Will-Dickson Thank You!!! that did the trick. i have them both communicating. However, the rodeostat only starts to read the arduino message after i press return in the serial monitor, is there some kind of Ready or begin message its expecting?



  • @HoughA Great. I'm glad to hear you got it working.

    Another option, if you really want a hardware serial port, is the other header P14. The pins D26 and D31 on that header can be used at the Rx and Tx pins for Serial2. See the serial docs for the various teensys here https://www.pjrc.com/teensy/td_uart.html

    Regarding pressing return in the serial monitor. The potentiostat's MessageReceiver, implemented in ps_message_receiver.h and ps_message_receiver.cp, only decides that a new message has arrived after receiving the '\n' character. The Arduino Serial Monitor sends a '\n' when you press return ... so could be that. Maybe adding a '\n' to the end of all messages sent to the teensy would help.



  • @Will-Dickson Thats actually what i ended up doing to get it to work!

    in regards to the serial problem, i tried adding a Serial2.print("\n"); as well as Serial2.println();. Neither one is getting it to work. any other ideas?



  • Even when i have the usb serial.begin for the rodeostat nothing happens, but i can still open serial monitor and press return or send any kind of code and the rodeo stat begins reading the arduino.



  • @Will-Dickson Another question is what is the highest frequency that the Sinusoidal voltammetry can operate at?



  • @HoughA

    There are a couple things that come into this.

    First, the output voltages are set at discrete time points via the testTimer which run by default at 5kHz. To make a reasonable approximation of a sine wave you will probably want enough points - maybe 50 or so. So you could probably output reasonable approximations of sinusoids voltages up to frequencies of about 100Hz.

    Second, the data is not sent back to the PC (or other device connected via UART) at every update of the testTimer. Rather it is sent at a lower sub-sampled rate set by the sample rate (or actually sample period in the firmware). The maximum value for the sample frequency is 1000Hz. You will need sufficient number of sample points at which to measure the current you get in response to the sine wave output. So maybe 20 or 30 or 50 ... the exact number depends on your needs. Lets say that 20 is sufficient. Then this further reduces the maximum sinusoid frequency to 50Hz (1000/20).

    Third you will need to take into account the bandwidth of the current measurement range you are using e.g. +/- 1uA, +/-10uA, +/-100uA, +/-1000uA. Each of these channels will lowpass filter the measure signal to some extent based on the resistor capacitor combination used in the feedback network of the transimpedance amplifier. The more sensitive channels will have lower cutoff frequencies. The +/-1000uA and +/-100uA channels have pretty high cut off frequencies such that it won't be an issue. However, the +/-10 uA and +/- 1uA ranges have cutoff frequencies of approximately 47Hz and 4.7Hz respectively. So if you are using these channels this will limit the bandwidth of your measurements somewhat or at least you should be aware of the possible attenuation of the measurements at higher frequencies.



  • @HoughA It will be awesome if you could post your arduino/teensy codes and some kind of schematic for the rest of us that are still fighting with this issue!

    Thank you!



  • Ey guys, after working on this along the afternoon I have solved the issues in our case.

    For the future generations that want to integrate Rodeostat in their Arduino based platforms:

    1. The Hardware: As Will has said before, you will need to connect the Arduino to the teensy in one of the possible ways (SoftwareSerial, I2C, SPI, Hardware Serial (like Serial2...)). In our case we have connected it by Hardware Serial, with Serial2 in the pins 26 of the P14 connector (see the schematic that Will attached before, remeber that the arrow in the pcb indicate the first pin of the header) to a TX pin in the Arduino (in our case the TX2 pin in Arduino Mega) and the 31 (also in the P14 connector) to the RX pin in the Arduino. For powering the rodeostat you will also need to connect the ground from teensy (like the one in the P13 or P14 connector) to the ground in Arduino, and 5V of Arduino to the pin 5V in the teensy PCB. This last pin is located under the P13 connector, there are four pins and the sign "5V" are near the internal pin of the PCB but TAKE CARE the 5V pin is the one in front of this, the one near the border of the PCB. That letters lead to an error.

    2. The Arduino software. You could use the one that @HoughA have post before, measuring the voltage between the "DAC BIP" hole in the pcb and a hole connected to ground. The voltage should change between 1 and 0 every second (if you polymeter don´t change this fast, just change the code and set a delay of 5 secs).

    3. Teensy software. First of all, you will need to add this lines to the setup function in the Arduino file (these lines are specific if you are using Serial2 communication, substitutes them for your own system):

    Serial2.setTX(31);
    Serial2.setRX(26);
    Serial2.begin(115200);
    

    You will need also to change the functions that receive the messages from the normal usb serial port, and set them to receive by Serial2 port instead. For doing this just open the files ps_message_receiver.cpp and ps_message_sender.cpp (this one if you want to also receive the response in your arduino instead of your PC) from the potentiostat library and change every line in which you see "Serial." to "Serial2."

    If you made only this changes you will have the problem that @HoughA have faced before; Your Arduino and your Teensy only communicates after you send something over the normal Serial port with a PC. This is because we don't have changed the Serial Event handler in the Arduino code. This handler triggers on with a new Serial communication and updates the message data.

    This handler function is located at the bottom of your .ino file. Is called SerialEvent and you will need to change it to SerialEvent2 (To handle Serial2 events instead of Serial events).

    Sorry for my poor English. Hope this comment has given you a hand.

    Hugs from Madrid,

    Fran


Log in to reply