Obtaining Multiple Outputs from a function;

Hi I am trying to figure out how I can get multiple outputs from the function I have for creating 8-bit RGB values.
I am certain the current method does not work - will I need to create a structure? or global variable? please let me know what is the optimal way,I am pretty new to coding with C

//initializations
int k; //counter variable
int n = 3; //set to 256
//int iter = 3; //RGB columns
int Niter = n * n * n;
int Rval;
int Gval;
int Bval;
int redP = 7; //pinnumber
int blueP = 8; //pinnumber
int greenP = 9; //pinnumber
// function declaration
int vals[1][3];



void setup() {
  Serial.begin(9600);
  pinMode(redP, OUTPUT);
  pinMode(blueP, OUTPUT);
  pinMode(greenP, OUTPUT);
}

void loop() {
  Rval = 0;
  Gval = 0;
  Bval = 0;

  for (k = 1; k <= Niter; k = k + 1) {
    analogWrite(blueP, Bval);
    Serial.print(Bval);
    Serial.print(" ");
    analogWrite(greenP, Gval);
    Serial.print(Gval);
    Serial.print(" ");
    analogWrite(redP, Rval);
    Serial.println(Rval);
    delay(10);
    vals[1][3] = RGB(Bval,Gval,Rval,n); //problem is here; how do I extract the values
    Bval = RGB[0];
    Gval = RGB[1];
    Rval = RGB[2];
  }
  delay(1000);
  Serial.println("");
}

int RGB(int Bval, int Gval, int Rval, int n) {

  if (Bval < (n - 1)) {
    Bval = Bval + 1;
  }
  else {
    Bval = 0;
  }
  val[1][1]= Bval;

  if (Gval < (n - 1)) {
    Gval = Gval + 1;
  }
  else {
    Gval = 0;
  }
  val[1][2] = Gval;

  if (Rval < (n - 1)) {
    Rval = Rval + 1;
  }
  else {
    Rval = 0;
  }
  val[1][3]=Rval;
}

returning a struct is one way, but you can also pass parameters by reference or pointer and update those directly in the function

here is an example (run with Serial console at 115200 bauds)

void updateVariablesRef(int &a, int &b) // by reference
{
  a = 12;
  b = 13;
}

void updateVariablesPtr(int *a, int *b) // by pointer
{
  *a = 56;
  *b = 78;
}

void setup() {
  Serial.begin(115200);
  int v1 = 22, v2 = 33;
  Serial.print(("\nBefore: ")); Serial.print(v1); Serial.write(' '); Serial.println(v2);
  updateVariablesRef(v1, v2);
  Serial.print(("After by reference: ")); Serial.print(v1); Serial.write(' '); Serial.println(v2);
  updateVariablesPtr(&v1, &v2); // we pass the address of the variables
  Serial.print(("After by Pointer: ")); Serial.print(v1); Serial.write(' '); Serial.println(v2);
}

void loop() {}

Serial Monitor (@ 115200 bauds) will show

[color=purple]
Before: 22 33
After by reference: 12 13
After by Pointer: 56 78
[/color]

so you can see the functions did their job

What value(s) do you want to return from which function?

val[1][1]= Bval;

val is not in scope. Is that supposed to be vals?

You should get a warning on the RGB function because it is supposed to return an int, but there is no return() in the function.

or with a struct as reference parameter

struct tRGB {
  byte red;
  byte green;
  byte blue;
};

void updateRBG(tRGB &v)
{
  v.red = 10;
  v.green = 20;
  v.blue = 30;
}

void setup() {
  tRGB variable = {99, 98, 97};
  Serial.begin(115200);
  Serial.print(("Before:\tRed=")); Serial.print(variable.red);
  Serial.print((" Green=")); Serial.print(variable.green);
  Serial.print((" Blue=")); Serial.println(variable.blue);

  updateRBG(variable);

  Serial.print(("After:\tRed=")); Serial.print(variable.red);
  Serial.print((" Green=")); Serial.print(variable.green);
  Serial.print((" Blue=")); Serial.println(variable.blue);
}

void loop() {}

or with the function returning a structure

struct tRGB {
  byte red;
  byte green;
  byte blue;
};

tRGB calculateRBG()
{
  tRGB v;
  v.red = 10;
  v.green = 20;
  v.blue = 30;
  return v;
}

void setup() {
  tRGB variable = {99, 98, 97};
  Serial.begin(115200);
  Serial.print(("Before:\tRed=")); Serial.print(variable.red);
  Serial.print((" Green=")); Serial.print(variable.green);
  Serial.print((" Blue=")); Serial.println(variable.blue);

  variable = calculateRBG();

  Serial.print(("After:\tRed=")); Serial.print(variable.red);
  Serial.print((" Green=")); Serial.print(variable.green);
  Serial.print((" Blue=")); Serial.println(variable.blue);
}

void loop() {}

in both cases Serial Monitor (@ 115200 bauds) will show

[color=purple]
Before: Red=99 Green=98 Blue=97
After: Red=10 Green=20 Blue=30
[/color]

groundFungus:
What value(s) do you want to return from which function?

val[1][1]= Bval;

val is not in scope. Is that supposed to be vals?

You should get a warning on the RGB function because it is supposed to return an int, but there is no return() in the function.

my bad;
val is supposed to be an array that consists the values for R, G and B - basically a 1x3 array - I am so used to python and MATLAB that I made that mistake. The returns should be the values for R G and B

you can't return an array by value in C++ (unless you wrapped it into a structure)

J-M-L:
returning a struct is one way, but you can also pass parameters by reference or pointer and update those directly in the function

here is an example (run with Serial console at 115200 bauds)

void updateVariablesRef(int &a, int &b) // by reference

{
 a = 12;
 b = 13;
}

void updateVariablesPtr(int *a, int *b) // by pointer
{
 *a = 56;
 *b = 78;
}

void setup() {
 Serial.begin(115200);
 int v1 = 22, v2 = 33;
 Serial.print(("\nBefore: ")); Serial.print(v1); Serial.write(' '); Serial.println(v2);
 updateVariablesRef(v1, v2);
 Serial.print(("After by reference: ")); Serial.print(v1); Serial.write(' '); Serial.println(v2);
 updateVariablesPtr(&v1, &v2); // we pass the address of the variables
 Serial.print(("After by Pointer: ")); Serial.print(v1); Serial.write(' '); Serial.println(v2);
}

void loop() {}




Serial Monitor (@ 115200 bauds) will show


Before: 22 33
After by reference: 12 13
After by Pointer: 56 78



so you can see the functions did their job

I am new to C, why would one set the address of a and b be beneficial -
coming from a background of Python and MATLAB - my go to solution was to create an array that will house the values for R,G and B for that single iteration.
thus val.
val tried to be a 1x3 array, but C does not work like that.
I want to grab the values, for R, G and B, from my function - then I would like to assign it to the Rval, Gval and Bval variables in my loop() function.

I can't seem to understand your method exactly :confused:

hansherath:
I can't seem to understand your method exactly :confused:

Those were just simple example to show how parameters can be used to pass back values

==> look at the example with the structures then (in post #3).

J-M-L:
Those were just simple example to show how parameters can be used to pass back values

==> look at the example with the structures then (in post #3).

I took your advice and read the structures documentation, I believe I made a valid tag to store my RGB values that a byte each (8-bit color). However, there seems to be an issue as the values are not being assigned. Do you believe my assignments are written wrong?

//initializations
int k; //counter variable
int n = 2; //set to 256
int Niter = n * n * n;
int Rval; //0-256 value for Red
int Gval; //0-256 value for Green
int Bval; //0-256 value for Blue
int redP = 7; //pinnumber for AnalogWrite
int blueP = 8; //pinnumber for AnalogWrite
int greenP = 9; //pinnumber for AnalogWrite
// structure declaration
struct RGB {
  int R;
  int G;
  int B;
} RGBvals;



void setup() {
  Serial.begin(115200);
  pinMode(redP, OUTPUT);
  pinMode(blueP, OUTPUT);
  pinMode(greenP, OUTPUT);
}

void loop() {
  Rval = 0;
  Gval = 0;
  Bval = 0;

  for (k = 1; k <= Niter; k = k + 1) {
    analogWrite(blueP, Bval);
    Serial.print(Bval);
    Serial.print(" ");
    analogWrite(greenP, Gval);
    Serial.print(Gval);
    Serial.print(" ");
    analogWrite(redP, Rval);
    Serial.println(Rval);
    delay(10);
    
    Bval = RGBvals.B;
    Gval = RGBvals.G;
    Rval = RGBvals.R;
  }
  delay(1000);
  Serial.println("");
}

int RGB(int Bval, int Gval, int Rval, int n) {

  if (Bval < (n - 1)) {
    Bval = Bval + 1;
  }
  else {
    Bval = 0;
  }
  RGBvals.B= Bval;

  if (Gval < (n - 1)) {
    Gval = Gval + 1;
  }
  else {
    Gval = 0;
  }
  RGBvals.G = Gval;

  if (Rval < (n - 1)) {
    Rval = Rval + 1;
  }
  else {
    Rval = 0;
  }
  RGBvals.R=Rval;
}

RGBvals structure is never initialized to anything so all elements are 0.

What is this function supposed to do? It suspiciously has the same name as the structure type.

int RGB(int Bval, int Gval, int Rval, int n) {
  if (Bval < (n - 1)) {
    Bval = Bval + 1;
  }
  else {
    Bval = 0;
  }
  RGBvals.B= Bval;

  if (Gval < (n - 1)) {
    Gval = Gval + 1;
  }
  else {
    Gval = 0;
  }
  RGBvals.G = Gval;

  if (Rval < (n - 1)) {
    Rval = Rval + 1;
  }
  else {
    Rval = 0;
  }
  RGBvals.R=Rval;
}

The goal of this code is to create all the 8-bit color combinations for an RGB LED.

I know code for this exists but I want to write my own and struggle to learn C, it is different from the languages I am familiar with.

Basically, there is a nested for loop (with 3 for loops) that computes all 16 million possible combinations; the function RGB (which should be renamed to RGB_strength -i.e. how strong each LED lights up) aids in the creation of the values from 0 to 256.

I struggle to get the values to output from the RGB_strength function; I ran the same code in MATLAB and it works like a charm - but in C, I need structures for assignment.

...and I do not know why the values are all 0 0 0, I thought I initialized it by writing

// structure declaration
struct RGB {
  int R=0;
  int G=0;
  int B=0;
} RGBvals;

this is my updated code- please point out what I am doing wrong

//////////////////initializations/////////////////////////////////////////////////////////

int k; //counter variable
int n = 2; //set to 256
int Niter = n * n * n;
int Rval; //0-256 value for Red
int Gval; //0-256 value for Green
int Bval; //0-256 value for Blue
int redP = 7; //pinnumber for AnalogWrite
int blueP = 8; //pinnumber for AnalogWrite
int greenP = 9; //pinnumber for AnalogWrite

// structure declaration
struct RGB {
  int R=0;
  int G=0;
  int B=0;
} RGBvals;

///////////////////////SET-UP FUNCTION////////////////////////////////////////////////////////////

void setup() {
  Serial.begin(115200);
  pinMode(redP, OUTPUT);
  pinMode(blueP, OUTPUT);
  pinMode(greenP, OUTPUT);
}

/////////////////////LOOP FUNCTION//////////////////////////////////////////////////

void loop() {
  Rval = 0;
  Gval = 0;
  Bval = 0;

  for (k = 1; k <= Niter; k = k + 1) {
    analogWrite(blueP, Bval);
    Serial.print(Bval);
    Serial.print(" ");
    analogWrite(greenP, Gval);
    Serial.print(Gval);
    Serial.print(" ");
    analogWrite(redP, Rval);
    Serial.println(Rval);
    delay(10);
    //get the values created using RGB_strength - to be used in analogwrite
    Bval = RGBvals.B;
    Gval = RGBvals.G;
    Rval = RGBvals.R;
  }
  delay(1000);
  Serial.println("");
}

//////////////FUNCTION TO GET VALUES FOR EACH R,G,B////////////////////////////////////////////////////////////////////////////

int RGB_strength(int Bval, int Gval, int Rval, int n) {

  if (Bval < (n)) {
    Bval = Bval + 1;
  }
  else {
    Bval = 0;
  }
  RGBvals.B= Bval;

  if (Gval < (n)) {
    Gval = Gval + 1;
  }
  else {
    Gval = 0;
  }
  RGBvals.G = Gval;

  if (Rval < (n)) {
    Rval = Rval + 1;
  }
  else {
    Rval = 0;
  }
  RGBvals.R=Rval;
}

You never use RGB_strength in your code

And, if you want to "compute" all colors of an RGB LED, why not simply count from 0 to 0xFFFFFF (so 16777216 times) and split this number in 3 bytes ? Like this, for example

void loop()
{
  static uint32_t color = 0;

  uint8_t r = color & 0xFF;
  uint8_t g = (color >> 8) & 0xFF;
  uint8_t b = (color >> 16) & 0xFF;

  analogWrite(redP, r);
  analogWrite(greenP, g);
  analogWrite(blueP, b);

  color++;
}

how can I incorporate RGB_strength in my loop;
I really do not understand the assignment in C, I created a structure that houses the values. Could you tell me how I can fix it?

*I have been working on this for the past 2 days - I really would like to figure out what is wrong

hansherath:
I really do not understand the assignment in C

You keep talking about C, but Arduino uses C++, which is a different language.

Have you tried following a C++ tutorial? All of this stuff is covered in C++ books, courses and tutorials. A forum thread is not the right format to learn the basics of a programming language.

Pieter

In the code that you posted in your previous message, you never call the function RGB_strength.

You need to call it whenever you want your global variable "RGBvals" to be updated

...
//get the values created using RGB_strength - to be used in analogwrite
RGB_strength(Bval, Gval, Rval, k);
Bval = RGBvals.B;
Gval = RGBvals.G;
Rval = RGBvals.R;
...

It should work, but it's really clumsy, not the proper way to do it

Did you see the simpler code in my previous message ?

PieterP:
You keep talking about C, but Arduino uses C++, which is a different language.

Have you tried following a C++ tutorial? All of this stuff is covered in C++ books, courses and tutorials. A forum thread is not the right format to learn the basics of a programming language.

Pieter

Thanks, I shall :slight_smile:

guix:
In the code that you posted in your previous message, you never call the function RGB_strength.

You need to call it whenever you want your global variable "RGBvals" to be updated

...

//get the values created using RGB_strength - to be used in analogwrite
RGB_strength(Bval, Gval, Rval, k);
Bval = RGBvals.B;
Gval = RGBvals.G;
Rval = RGBvals.R;
...



It should work, but it's really clumsy, not the proper way to do it

Did you see the simpler code in my previous message ?

Thanks for the reply! It works now - I really appreciate it.
I am reading through your code; it is far more elegant. Thank you!

My code may be more elegant, but it probably doesn't do what you really want :slight_smile: It will loop all colors, but slowly and not in a nice order

About your code, you don't need that "RGBvals" variable. Since the beginning of this topic you have been given the (or one) answer: you should use "references", which mean that you give the memory addresses of the variables to the function, so the function can directly modify the value of these variables, without making copies of them, and without having to return anything

See this to understand: C++ function call by reference

Basically, there is a nested for loop (with 3 for loops) that computes all 16 million possible combinations; the function RGB (which should be renamed to RGB_strength -i.e. how strong each LED lights up) aids in the creation of the values from 0 to 256.

if you want three nested "for" loops you can do this

void loop()
{
  for (int r = 0; r < 256; r++) {
    analogWrite(redP, r);
    for (int g = 0; g < 256; g++) {
      analogWrite(greenP, g);
      for (int b = 0; b < 256; b++)  {
        analogWrite(blueP, b);
      }
    }
  }
}