Hi there,
I have been presented with problem of controlling mass-flow controller for the 4 micro-fluid pumps that guys from lab got. The mass-flow controller is connected to the Arduino nano, which is then trough USB connected to the computer. The people who sold them this machine produce as well a demo code for arduino. Sadly there is no comment to speak of at all.
This is the demo code. As I understand it it should run trough the switch statements based on input, but I never manage to figure out how to produce the right input to make it work.
I know that this code work at least partially because I manage to make it work in a way.
If I write it like this I can create sort of script that board is reacting on correctly.
The problem is that while I could be able to work with it like this others might not. To make it easier to my colleges I decided to create a windows based application in C# that could send inputs to the arduino code and initialize it with simple "click" of the button.
For that purpose i try to change the original code slightly:
void loop() {
if (Serial.available() > 0) { // Check to see if there is a new message
mode = Serial.read(); // Put the serial input into the message
switch (mode)
{
case MODE_OFF:
Wire.beginTransmission(Addr);
Wire.write(I2C_POWERMODE); // start adress
Wire.write(0x00); // disable
Wire.endTransmission();
digitalWrite(LED,LOW);
break;
case MODE_50:
Wire.beginTransmission(Addr);
Wire.write(I2C_POWERMODE); // start adress
Wire.write(0x01); // enable
Wire.write(0x00); // 50 Hz
Wire.endTransmission();
digitalWrite(LED,HIGH);
break;
case MODE_100:
Wire.beginTransmission(Addr);
Wire.write(I2C_FREQUENCY); // start adress
Wire.write(0x40); // 100 Hz
Wire.endTransmission();
break;
case MODE_200:
Wire.beginTransmission(Addr);
Wire.write(I2C_FREQUENCY); // start adress
Wire.write(0x80); // 200 Hz
Wire.endTransmission();
break;
case MODE_400:
Wire.beginTransmission(Addr);
Wire.write(I2C_FREQUENCY); // start adress
Wire.write(0xC0); // 400 Hz
Wire.endTransmission();
break;
case MODE_800:
Wire.beginTransmission(Addr);
Wire.write(I2C_FREQUENCY); // start adress
Wire.write(0xFF); // 800 Hz
Wire.endTransmission();
break;
}
debounce|=0x01;
}
} else {
if (debounce&0x01) {
debounce&=~0x01;
}
}
delay(100);
}
Sorry I posting it like this but my original post was too big
here is the c# code I using to send inputs:
namespace Arduino_try
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
serialPort1.PortName = "COM6";
serialPort1.BaudRate = 9600;
}
private void button1_Click(object sender, EventArgs e)
{
serialPort1.Open();
if (serialPort1.IsOpen)
{
serialPort1.WriteLine("MODE_OFF");
}
serialPort1.Close();
}
private void button2_Click(object sender, EventArgs e)
{
serialPort1.Open();
if (serialPort1.IsOpen)
{
serialPort1.WriteLine("MODE_50");
}
serialPort1.Close();
}
}
}
Now I know that the board getting some signals from the app thanks to the led lights flashing.
Now my question to people on this forum is. Does anyone see some way to modify the original arduino code from up so it could receive the input from serial port. And if anyone can make some sense from the original code from the top of this post and explain it (the loop() part) to me, that would be most helpful as well
You need a datasheet of the device. Which sensor is it ? Or is it not a sensor but a microcontroller ? Then at least you need a description of all the registers. Just a few registers that are called P1VOLTAGE and so on, that is not enough. It is not a sensor, but a controller ? And data is only written to it ? Can you make a photo of the controller that shows the chips inside ?
Some devices require a special sequence to wake up. Perhaps it is possible to read from it to check the hardware.
I believe that it is microcontroller. Mainly there is no sensor only 4 plug-ins for the miro pumps. I think there is no need for it to give any data back, except for ON/OFF on the four pumps connected. Also do I really need more registers, even tho it kind of worked, if I initialize it in the setup function as "ON" (0x01)?
Sadly I am unable to go to lab until thursday so I need to wait for my colleague to get me all the data that came with the board (and the picture).
Can you describe what is not working and what do you want it to do ?
You define commands with binary numbers, but perpaps you want to type ascii numbers ? and the C# uses text strings. You should use the same thing for everything.
What do you want for a command ? Command "A" is easy. Command "MODE_OFF" is not so easy, because you have to determine where the command begins and where it ends.
Do you want to be able to type the commands, to test the communication with a terminal ?
If you use a terminal, a line could be terminated with '\r' or with '\n' or with both or with none.
I prefer a start byte and stop byte. That could be binary codes of stx and etx, but also readable bytes, for example "#A150!" to transmit command that 'A' must be set to 150.
There is also code to read serial commands, I can't find it right now, but they are mentioned now and then on this forum.
As I understand it it should run trough the switch statements based on input, but I never manage to figure out how to produce the right input to make it work.
There should be a push button (connected between pin3 and ground), and each time it is pushed it will change the mode. Do you have the switch installed, and does it change the frequencies?
And if anyone can make some sense from the original code from the top of this post and explain it (the loop() part) to me, that would be most helpful as well
The loop just looks for input from the push button, switches case based on the number of pushes, and sets the registers for on/off and frequency(pump soeed?) using 12c commands. What specifically do you not understand?
Does anyone see some way to modify the original arduino code from up so it could receive the input from serial port.
What happened with your attempt
if (Serial.available() > 0) { // Check to see if there is a new message
mode = Serial.read(); // Put the serial input into the message
switch (mode)
{
Try change the code to input 0-10 instead of ascii and don't switch if there is not a new mode
byte mode;
byte lastMode;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0)
mode = Serial.read() - '0';
if (mode != lastMode)
{
switch (mode)
{
case 1:
Serial.println("mode 1");
lastMode = 1;
break;
case 2:
Serial.println("mode 2");
lastMode = 2;
break;
case 3:
Serial.println("mode 3");
lastMode = 3;
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
}
}
The user input is pretty poor in the code you inherited. You may want to work with a labeled rotary switch, or Serial input with prompts. I'd separate the user interface development from getting the device to work with basic Serial input from the monitor. You may want to review Robin2's excellent tutorial on Serial input.
Koepel: What I trying to do is send a simple command that would say. Start the pump with this frequency (Hz) so that it is possible to control the speed of the fluid and also to be able to switch it off and on. (So i dont need to upload entire code to the board again ).
I dont really need to be "comand_off" it it can be called comand "A", but what I need to be able is to send and input lets say commmand "A", which would start the mode with frequency 50Hz etc. Best if I can recive this inpute from serial port so I can create window-form aplication which would make it morea eassly to controle for people who dont know a think abbout code. Yes I would like to be able to tape that comand or send it from the C#.
cattledog: yes there is Push button on the side of the massflow controler, but it is very inconvenient way of controling it becouse each push go from one mode to the other (from off to max), which is not good in terms of precision. (And with microfluid there is apparently great need for precision).
Since I never used Arduino before I didn't realize that loop looks for input from button. Pardon my
mistake.
My attempt to modify it as I posted didn't do anything. Perhaps because I tried to send "MODE OFF" etc. which was not taken as full string?
But knowing that this loop was asking for the input from button I might try to modify it and send only case 1 case 2 etc. as per your suggestion. Sadly I going to get my hand on that board in Thursday not sooner, so I dont really see anz changes before that. But thank you very much for your advices :).
The loop() runs over and over again, run Serial.available() in the loop().
If something is available, perhaps check for isalpha().
After that it is possible to read the number with a parse function : Serial.parseInt() - Arduino Reference
Those parse functions have a timeout. If you don't use them, you have make some kind of timing to allow that the whole command is received.
I prefer that you add a newline to every line. It can be useful when debugging.
For example "A\n" for stop and "F500\n" for frequency set to 500.
void loop()
{
if( Serial.available() > 0)
{
int c = Serial.read();
if( isalpha(c))
{
switch( c)
{
case 'S':
// Stop
...
break;
case 'F':
// The number of HZ followes the 'F'
int frequency = Serial.parseInt();
...
break;
}
}
}
}
Because never worked with code that would have to be send to external hardware so I have no idea what would happen if I try to give the frequency actual number as value instead of using 0x01, 0xC0 etc.
if I try to give the frequency actual number as value instead of using 0x01, 0xC0 etc.
Wire.write() expects a byte, and it does not matter if the number is represented in binary, decimal or hex. Wire.write(128), wire.write(B10000000) and wire.write(0x80) are all the same if you wanted to set the frequency to 200Hz.
String frequencyHex = String(frequency, HEX); // convert input into hexadecimal
frequency = frequencyHex.toInt(); // conver string with hexadecimal into integeer
Forget about this stuff. First, you do not need the String objects to achieve what you need. You do not need the hex representation of the integer.
Did you study Robin2"s tutorial on Serial input? Follow his methods. You are designing the interface, so decide if you want the user to enter letters, numbers, word commands, whatever. Prompt the user, or provide a menu. Once you design in detail how you want the user input to be, the code will be straightforward.
It is best to have a start and end marker, and to wait for the end marker before you act on the command
Have a look at both tutorials.
The 'parse' functions were added later on. I don't use them often, but when I do, I set the timeout to 20ms or 100ms or so. The 'parse' functions are blocking, that means the Arduino can not run other code while waiting for the end of the serial input. I think they will be okay for your project.
The 'SerialEvent()' was also added, but we don't like it, since it is not an interrupt but only a polling function during every run of loop().