User-defined Sequence of Functions

Hello, I am very new to Arduino and C/C++ and would like some help in coding a power supply for work. It came with it's own code and I modified it to fit my company's needs. So far, the functions I have built into it are: setting current, setting voltage, and voltage/current ramping up or down, as well as user-friendly features like stopping any function whenever I enter a certain letter into the serial monitor or when a time limit is reached. I am using the serial monitor for all inputs because the end goal is to interface my program with a python GUI.

Anyways, the problem I am having is that I am unsure how to approach a function that would take in a function sequence from the user and execute the functions in that order. For example, the user inputs the sequence to set the current to 1 amp, then ramp up to 10 amps, hold the current at 10 amps for 20 seconds, then ramp down to 4 amps, etc. The sequence would need to be fully customizable, with as many sequence steps as they'd want (memory allowing).

I've looked into function pointers, classes/objects, but I am not exactly sure what the best method would be. Thank you all for reading and helping!

The first step is to write down on paper all the functions that a user might request. Without that list, you have no place to begin designing your system.

Paul

Sorry if it was overlooked, but I stated the possible functions that I had already written and work well. They are: setting current, setting voltage, and ramping. These could be looped as well if the user chooses to do so. Thank you!

You say that the eventual aim is to have Python program send the data to the Arduino. With that in mind think of the commands in a very minimal style - because the Python program can convert the user input into any form you like. Do as much as possible of the hard work in Python and make the job of the Arduino as simple as possible.

For example if you want to send a sequence of Current, Volts and Ramp to the Arduino you could send it like this
<23,75,50>
where the first value is always the current, the second the voltage and the third the ramp value (I've no idea what that might look like)

If that style is not suitable please explain why so that we can give better advice.

...R

Robin2:
For example if you want to send a sequence of Current, Volts and Ramp to the Arduino you could send it like this
<23,75,50>
where the first value is always the current, the second the voltage and the third the ramp value (I've no idea what that might look like)

If that style is not suitable please explain why so that we can give better advice.

...R

It would be possible, albeit more complicated than that given how the arduino is hooked up to the power supply. I would simply need to pass more parameters and have an if statement to differentiate between a constant current/constant voltage state and a ramping state.

I apologize for not posting any code here. I understand that makes helping more difficult. It is just that the code is too complex because of how it came pre-coded. It took me a month to figure out what all the built-in functions do, and another month to get to where I am now.

Having said that, I appreciate any and all possible routes that one might take in approaching a sequence function.

blee630:
Sorry if it was overlooked, but I stated the possible functions that I had already written and work well. They are: setting current, setting voltage, and ramping. These could be looped as well if the user chooses to do so. Thank you!

I based my reply on your statement: "The sequence would need to be fully customizable, with as many sequence steps as they'd want (memory allowing).".

Unless you intend to program an interpreter for your Arduino, all your parameters have to be allowed for in the original code.

Paul

Perhaps you can take a moment and explain what the Arduino is doing that the PC/Python can't do.

Paul

Paul_KD7HB:
I based my reply on your statement: "The sequence would need to be fully customizable, with as many sequence steps as they'd want (memory allowing).".

I see the misunderstanding. What I meant by it being fully customizable was not in the functions themselves, but the order in which the user sequences the functions.

In terms of what the arduino is doing, it is telling the power supply what to do. The manufacturer made it so that the arduino is housed inside the power supply so I cannot access it to rewire it. The only way I can tell the power supply what to do is through the arduino. I know more arduino coding than I do python (I actually don't know any python and I need to learn it to complete this project), so I chose to code the Arduino first and then have it interface with Python later.

Based on years of experience, may I suggest you program the Arduino as simple a pass-through from the PC to the PSU, and do ALL the work on the PC using Python or something similar. Otherwise you will be maintaining both sets of software and chasing bugs from one machine to the other and back again. Limit your exposure to problems to a single source.

Good luck
Paul

blee630:
It would be possible, albeit more complicated than that given how the arduino is hooked up to the power supply. I would simply need to pass more parameters and have an if statement to differentiate between a constant current/constant voltage state and a ramping state.

Without some clear examples of all the options and how they need to be handled I can't see how I can help further.

In my example there are only 3 items, but you could easily extend that to a dozen or more. And you could perhaps have a special value that indicates to the Arduino that an item should be ignored.

...R

blee630:
Anyways, the problem I am having is that I am unsure how to approach a function that would take in a function sequence from the user and execute the functions in that order. For example, the user inputs the sequence to set the current to 1 amp, then ramp up to 10 amps, hold the current at 10 amps for 20 seconds, then ramp down to 4 amps, etc. The sequence would need to be fully customizable, with as many sequence steps as they'd want (memory allowing).

I've looked into function pointers, classes/objects, but I am not exactly sure what the best method would be. Thank you all for reading and helping!

How about an array of function pointers and parameters stored as uint16_t commandString[ 20 ] and an index byte csidx and limit cslim? The function reads parameters off the string as ints while incrementing the index. Function finishes, check if there's a next one, etc. When the string is done, everything stops.

How does the user enter the sequence?

Text? With or without help from the Arduino? I have a word matcher that associates functions with names and so far runs the function when the name is entered. The word list and link data are kept in flash capable of holding 1000's of words on an Uno. Read the name, run the function. Let the function read following parameters.

Numbers? You don't have to match names if you already have the numbers. But you gotta be smarter.

GoForSmoke:
How about an array of function pointers and parameters ...

I can't help feeling that a much simpler solution will be adequate.

We await more info from the OP as to what sort of inputs the Arduino will get and how it ought to respond to them.

...R

I got started on how the user inputs the sequence and it works well. This gives me an array of integers that correspond to some function of the power supply. I would then need the user to give it settings for each step (like funcN = 0, set current to x value). I was thinking of having a switch case based on the array given by this function.
* *int sequenceOrder(unsigned long x) {   int funcN[x];   for (int i = 0;i < x; i++) {     while (!Serial.available()) {     }     int input; // 0 = set current, 1 = set voltage, 2 = ramp current up, 3 = ramp current down, 4 = ramp voltage up, 5 = ramp voltage down     delay(8);     input = Serial.parseInt();     funcN[i] = input;     Serial.println(funcN[i]);     }   return funcN; }* *

blee630:
I got started on how the user inputs the sequence and it works well. This gives me an array of integers that correspond to some function of the power supply. I would then need the user to give it settings for each step (like funcN = 0, set current to x value). I was thinking of having a switch case based on the array given by this function.
[/quote]
Please put the idea of code out of your mind for a while and just describe the requirement in English with examples of the sorts of thing that the Arduino should be able to deal with.
When we understand the requirement it will be much easier to give advice.
Without a clear statement of the requirement you are more likely to find yourself with a camel when what would really have suited the project is a horse.
...R

blee630:
I got started on how the user inputs the sequence and it works well. This gives me an array of integers that correspond to some function of the power supply. I would then need the user to give it settings for each step (like funcN = 0, set current to x value). I was thinking of having a switch case based on the array given by this function.
* *int sequenceOrder(unsigned long x) {   int funcN[x];   for (int i = 0;i < x; i++) {     while (!Serial.available()) {     }     int input; // 0 = set current, 1 = set voltage, 2 = ramp current up, 3 = ramp current down, 4 = ramp voltage up, 5 = ramp voltage down     delay(8);     input = Serial.parseInt();     funcN[i] = input;     Serial.println(funcN[i]);     }   return funcN; }* *
[/quote]
Okay, that's the number code approach. But set voltage to how many mV? Current to how many mA?
With function by number you make an array of function pointers and then instruction number is the index.
But you want to avoid all that blocking code in your routine which btw has no switch-case structure at all.

doesn't compile, not tested
```
*const byte maxCmnds = 40;  // includes passed values
byte cmndIndex = maxCmnds + 1;;
int command[ maxCmnds ];  // user commands get stored here
.....

void loop()
{
  if ( Serial.available() )
  {
    // code to read text from serial monitor and fill command[] and set cmndIndex to 0.
  }

if ( cmndIndex >= 0 && cmndIndex < maxCmnds )
  {
    switch( command[ cmndIndex ] )
    {
      case 0 :
        // run function 0
        // function may have its own state machine,  run many times before cmndIndex changes
        // function can use parameters stored in command[ cmndIndex + 1 to many ]
        // and when the function is done it sets cmndIndex ahead to the next function to run
      break;
      case 1 :
        // run function 1
      break;
      case 2 :
        // run function 2
      break;
      .....
    }
}*

```