RGB Model Analysis

Hi All,

Am working on understanding a code snippet for assigning a color value to RGB values. Would appreciate any insights.

The original code snippet was copied from here:

const int distinctRGB[22][3] = {{255, 255, 255},{0,0,0},{128,0,0},{255,0,0},{255, 200, 220},{170, 110, 40},{255, 150, 0},{255, 215, 180},{128, 128, 0},{255, 235, 0},{255, 250, 200},{190, 255, 0},{0, 190, 0},{170, 255, 195},{0, 0, 128},{100, 255, 255},{0, 0, 128},{67, 133, 255},{130, 0, 150},{230, 190, 255},{255, 0, 255},{128, 128, 128}};
const String distinctColors[22] = {"white","black","maroon","red","pink","brown","orange","coral","olive","yellow","beige","lime","green","mint","teal","cyan","navy","blue","purple","lavender","magenta","grey"};
String closestColor(int r,int g,int b) {
  String colorReturn = "NA";
  int biggestDifference = 1000;
  for (int i = 0; i < 22; i++) {
    if (sqrt(pow(r - distinctRGB[i][0],2) + pow(g - distinctRGB[i][1],2) + pow(b - distinctRGB[i][2],2)) < biggestDifference) {
      colorReturn = distinctColors[i];
      biggestDifference = sqrt(pow(r - distinctRGB[i][0],2) + pow(g - distinctRGB[i][1],2) + pow(b - distinctRGB[i][2],2));
    }
  }
  return colorReturn;
}

I set it up as a sketch

//===Global constants and variables

// RGB -> color mapping data
const int distinctRGB[22][3] = {{255, 255, 255}, {0, 0, 0}, {128, 0, 0}, {255, 0, 0}, {255, 200, 220}, {170, 110, 40}, {255, 150, 0}, {255, 215, 180}, {128, 128, 0}, {255, 235, 0}, {255, 250, 200}, {190, 255, 0}, {0, 190, 0}, {170, 255, 195}, {0, 0, 128}, {100, 255, 255}, {0, 0, 128}, {67, 133, 255}, {130, 0, 150}, {230, 190, 255}, {255, 0, 255}, {128, 128, 128}};
const String distinctColors[22] = {"white", "black", "maroon", "red", "pink", "brown", "orange", "coral", "olive", "yellow", "beige", "lime", "green", "mint", "teal", "cyan", "navy", "blue", "purple", "lavender", "magenta", "grey"};

// === Setup code, runs once =========================

void setup() {

}

// === Main code, loops endlessly ===================

void loop() 
{
  
void matchColor();

}

//===Breakout of functions ===========================

void matchColor()
{
String closestColor(int r, int g, int b)
  {
    String colorReturn = "NA";
    int biggestDifference = 1000; // 1000 > (255*3=765)
    for (int i = 0; i < 22; i++)
    {
      if (sqrt(pow(r - distinctRGB[i][0], 2) + pow(g - distinctRGB[i][1], 2) + pow(b - distinctRGB[i][2], 2)) < biggestDifference)
      {
        colorReturn = distinctColors[i];
        biggestDifference = sqrt(pow(r - distinctRGB[i][0], 2) + pow(g - distinctRGB[i][1], 2) + pow(b - distinctRGB[i][2], 2));
      }
    }
    return colorReturn;
  }
}

... and am getting the following error at

String closestColor(int r, int g, int b)
  {

a function-definition is not allowed here before '{' token

void matchColor()
{
  String closestColor(int r, int g, int b)

You are defining the closestColor() function inside the matchColor() function

Appreciate your review.

Reworked my sketch and I am able to get it to compile

//===Global constants and variables ==================

// RGB -> color mapping data
const int distinctRGB[22][3] = {{255, 255, 255}, {0, 0, 0}, {128, 0, 0}, {255, 0, 0}, {255, 200, 220}, {170, 110, 40}, {255, 150, 0}, {255, 215, 180}, {128, 128, 0}, {255, 235, 0}, {255, 250, 200}, {190, 255, 0}, {0, 190, 0}, {170, 255, 195}, {0, 0, 128}, {100, 255, 255}, {0, 0, 128}, {67, 133, 255}, {130, 0, 150}, {230, 190, 255}, {255, 0, 255}, {128, 128, 128}};
const String distinctColors[22] = {"white", "black", "maroon", "red", "pink", "brown", "orange", "coral", "olive", "yellow", "beige", "lime", "green", "mint", "teal", "cyan", "navy", "blue", "purple", "lavender", "magenta", "grey"};

const int r = 0;
const int g = 0;
const int b = 0;

// === Setup code, runs once =========================

void setup() {

  Serial.begin(9600);

}

// === Main code, loops endlessly ====================

void loop() 
{
  
void matchColor();

}

//===Breakout of functions ===========================

void matchColor()
  {

    String colorReturn = "NA";
    int biggestDifference = 1000; // 1000 > (255*3=765)
    for (int i = 0; i < 22; i++)
    {
      if (sqrt(pow(r - distinctRGB[i][0], 2) + pow(g - distinctRGB[i][1], 2) + pow(b - distinctRGB[i][2], 2)) < biggestDifference)
      {
        colorReturn = distinctColors[i];
        biggestDifference = sqrt(pow(r - distinctRGB[i][0], 2) + pow(g - distinctRGB[i][1], 2) + pow(b - distinctRGB[i][2], 2));
      }
    }
    return colorReturn;
  }

So ... next step that I see is: how do I test my code?

Simon Monk has shared a sketch for a morse code translator that provides a possible insight into how to map two data tables and use an LED to show the results.

/**************************************************
Simon Monk, Programming Arduino: Getting Started with Sketches, Second Edition 
  
  Morse code translator
  sketch 5-05
  https://github.com/simonmonk/programming_arduino

**************************************************/

// ==== Global variables and constants ============

const int dotDelay = 200;
const int ledPin = 13;

char* letters[] = {
  ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..",    // A-I
  ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.",  // J-R
  "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."          // S-Z
};

char* numbers[] = {"-----", ".----", "..---", "...--", "....-", 
  ".....", "-....", "--...", "---..", "----."};
 
// === Setup code, runs once =======================
 
void setup()                 
{
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

// === Main code, runs endlessly =================== 

void loop()                    
{
  char ch;
  if (Serial.available() > 0)
  {
    ch = Serial.read();
    if (ch >= 'a' && ch <= 'z')
    {
      flashSequence(letters[ch - 'a']);
    }
    else if (ch >= 'A' && ch <= 'Z')
    {
      flashSequence(letters[ch - 'A']);
    }
    else if (ch >= '0' && ch <= '9')
    {
      flashSequence(numbers[ch - '0']);
    }
    else if (ch == ' ')
    {
      delay(dotDelay * 4);  // gap between words  
    }
  }
}

// === Breakout of functions ======================

void flashSequence(char* sequence)
{
  int i = 0;
  while (sequence[i] != NULL)
  {
    flashDotOrDash(sequence[i]);
    i++;
  }
  delay(dotDelay * 3);    // gap between letters
}

void flashDotOrDash(char dotOrDash)
{
  digitalWrite(ledPin, HIGH);
  if (dotOrDash == '.')
  {
    delay(dotDelay);           
  }
  else // must be a dash
  {
    delay(dotDelay * 3);           
  }
  digitalWrite(ledPin, LOW);    
  delay(dotDelay); // gap between flashes
}

I am wondering if I can use the distinctRGB and distinctColor arrays (tables) and a TCS3200 light-to-frequency converter to test this code snippet in a similar way to Simon Monk.

Chipping away at assigning colors to RGB values generated by a sensor (TCS3200 light->frequency converter).

Is there a better way to approach this?

a. Less code = less space
b. Less rigid criteria = more than one set of RGB values can be mapped to "Green"

Code examples would be appreciated

//===Global constants and variables ==================

//  Mapping data:  RGBvalue <-> ColorDesignation
int RGBvalue[6][3] = {{0, 0, 0},{255, 0, 0}, {255, 235, 0}, {0, 255, 0}, {128, 128, 128}, {0, 0, 255}};
String ColorDesignation[6] = {"black", "red", "yellow", "green", "grey", "blue"};
#define String "black" = 10
#define String "red" = 11
#define String "yellow" = 12
#define String "green" = 13
#define String "grey" = 14
#define String "blue" = 15

//===Breakout of functions used in void loop ===========================

void colorMatch()
{ 
  if (redFreq == 0 && greenFreq == 0 && blueFreq == 0)
  {
    // Black detected
    Serial.print("Sensor sees Black");
    Serial.print(10);
  } 
  else if (redFreq == 255 && greenFreq == 0 && blueFreq == 0)
  {
    // Red detected
    Serial.print("Sensor sees Red");
    Serial.print(11);
  }
  else if (redFreq == 255 && greenFreq == 235 && blueFreq == 0)
  {
    // Yellow detected
    Serial.print("Sensor sees Yellow");
    Serial.print(12);
  }
  else if (redFreq == 0 && greenFreq == 255 && blueFreq == 0)
  {
    // Green detected
    Serial.print("Sensor sees Green");
    Serial.print(13);
  }
  else if (redFreq == 128 && greenFreq == 128 && blueFreq == 128)
  {
    // Grey detected
    Serial.print("Sensor sees Grey");
    Serial.print(14);
  }
  else if (redFreq == 0 && greenFreq == 0 && blueFreq == 0)
  {
    // Blue detected
    Serial.print("Sensor sees Blue");
    Serial.print(15);
  }
}

@Delta_G

Easy cowboy ...

My goal is to learn how to code and to improve by doing.

======================================

The code snippet that I provided is part of this program which compiles and runs ... just not as well as I would like it to.

//=== Libraries =====================================

#include "Math.h" // https://www.arduino.cc/en/math/h

//===Global constants and variables ==================

// TCS3200 light->frequency converter to i/o shield wiring assignments
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8

// sensor frequency range = 0 to 600 kHz
// byte = range of 0 to 255
// int = 16 bit = 2 byte value = range of -32,768 to 32,767 
int redFreq = 0;  //
int greenFreq = 0;  //
int blueFreq = 0;  //  for Blue photodiodes

//  Mapping data:  RGBvalue <-> ColorDesignation
int RGBvalue[6][3] = {{0, 0, 0},{255, 0, 0}, {255, 235, 0}, {0, 255, 0}, {128, 128, 128}, {0, 0, 255}};
String ColorDesignation[6] = {"black", "red", "yellow", "green", "grey", "blue"};
#define String "black" = 10
#define String "red" = 11
#define String "yellow" = 12
#define String "green" = 13
#define String "grey" = 14
#define String "blue" = 15

// === Setup code, runs once =========================

void setup() 
{

  // TCS3200 light->frequency converter
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(sensorOut, INPUT);

  // Set frequency-scaling to 20%
  digitalWrite(S0, HIGH);
  digitalWrite(S1, LOW);
  
  // Open serial monitor to view sensor readings at 9600 baud
  Serial.begin(9600);  

}

// === Main code, loops endlessly ====================

void loop() 
{

sensorReading();  
colorMatch();

}

//===Breakout of functions used in void loop ===========================

void sensorReading()
{
      
  // Read Red filtered photodiodes
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);
  // Reading the output frequency
  redFreq = pulseIn(sensorOut, LOW);
  // Remap the value of the Frequency to the RGB Model
  // Syntax - map(value, fromLow, fromHigh, toLow, toHigh)
  // Frequency Model fromLow = (0, 0) to fromHigh = (594, 600)  (calculated kHz, theory kHz) from sensor spec sheet
  // RGB Model toLow = 0, RGB Model toHigh = 255
  redFreq = map(redFreq, 0, 594, 0, 255);

  // Read Green filtered photodiodes
  digitalWrite(S2, HIGH);
  digitalWrite(S3, HIGH);
  // Reading the output frequency
  greenFreq = pulseIn(sensorOut, LOW);
  // Remap the value of the Frequency to the RGB Model
  // Syntax - map(value, fromLow, fromHigh, toLow, toHigh)
  // Frequency Model fromLow = (0, 0) to fromHigh = (480, 600)  (calculated kHz, theory kHz) from sensor spec sheet
  // RGB Model toLow = 0, RGB Model toHigh = 255
  greenFreq = map(greenFreq, 0, 480, 0, 255);

  // Read Blue filtered photodiodes
  digitalWrite(S2, LOW);
  digitalWrite(S3, HIGH);
  // Reading the output frequency
  blueFreq = pulseIn(sensorOut, LOW);
  // Remap the value of the Frequency to the RGB Model
  // Syntax - map(value, fromLow, fromHigh, toLow, toHigh)
  // Frequency Model fromLow = (30, 0) to fromHigh = (504, 600)  (calculated kHz, theory kHz) from sensor spec sheet
  // RGB Model toLow = 0, RGB Model toHigh = 255
  blueFreq = map(blueFreq, 30, 504, 0, 255);

  // Print Sensor Reading
  Serial.print("R = ");
  Serial.print(redFreq);
  Serial.print(" ");
  Serial.print("G = ");
  Serial.print(greenFreq);
  Serial.print(" ");
  Serial.print("B = ");
  Serial.print(blueFreq);
  Serial.print(" ");
  Serial.print("\n\n");
  delay(500);
}

void colorMatch()
{ 
  if (redFreq == 0 && greenFreq == 0 && blueFreq == 0)
  {
    // Black detected
    Serial.print("Sensor sees Black");
    Serial.print(10);
  } 
  else if (redFreq == 255 && greenFreq == 0 && blueFreq == 0)
  {
    // Red detected
    Serial.print("Sensor sees Red");
    Serial.print(11);
  }
  else if (redFreq == 255 && greenFreq == 235 && blueFreq == 0)
  {
    // Yellow detected
    Serial.print("Sensor sees Yellow");
    Serial.print(12);
  }
  else if (redFreq == 0 && greenFreq == 255 && blueFreq == 0)
  {
    // Green detected
    Serial.print("Sensor sees Green");
    Serial.print(13);
  }
  else if (redFreq == 128 && greenFreq == 128 && blueFreq == 128)
  {
    // Grey detected
    Serial.print("Sensor sees Grey");
    Serial.print(14);
  }
  else if (redFreq == 0 && greenFreq == 0 && blueFreq == 0)
  {
    // Blue detected
    Serial.print("Sensor sees Blue");
    Serial.print(15);
  }
}

@ Delta_G I am not mad and I strive keep my tone professional. Presumably you seek to act in a similar fashion. If my questions are not to your liking then please pass them by.

=================================

I am using the following resources to learn and am open to suggestions:

Lol lol

Forums are for questions and your emotional responses speak volumes.

Sifting though them I find the following useful information:

C++ tutorial

object oriented, classes and structs

A simple response could include

Consider a C++ tutorial like

Intro to C++ by edX

or

YouTube C++ Tutorial

and focus on the object oriented programming, classes and structs portions.

Here is an example of how to resolve issue x ....