Go Down

Topic: Create a proportional scale of numbers where 10 = 0 and 60 =255 (Read 844 times) previous topic - next topic

joeedel89

I have a sensor where the largest value I expect is 60 and the minimum is 10.  I have the code working but my leds never get very bright (255 is max brightness) or all the way off (10 is dim but not off).  The part of my code that pertains to the question looks like this.

  Serial.println(averageValue); // So I can see the reading
  for(int i = 0; i < 10; i++ ) {
    if (averageValue > 60)
    {
      averageValue = 60; // Limits high reading
    }
  leds.r = averageValue, leds.g = averageValue, leds.b=averageValue;
  }
  FastSPI_LED.show();

I would like to create a "scale" where 10 = 0 and 60 = 255 and all the numbers in between are proportional (ie. 10 = 0, 35 = 127.5, 60 = 255 and of course include all the other numbers in between)  I googled for a while but don't really even know what to call what I am looking for.

Thanks



robtillaart


and you can use constrain(x, lower, upper)  to limit the value.  But be aware it is a macro....

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

joeedel89

Thank you both, the map was what I was looking for makes prefect sense.  It seems when I try to constrain the arduino does weird things so I will work with that later.

  averageValue = map(averageValue,0,60,0,255);
  Serial.println(averageValue); // So I can see the reading
  for(int i = 0; i < 10; i++ ) {
    if (averageValue > 255)
    {
      averageValue = 255; // Limits high reading
    }
  leds.r = averageValue, leds.g = averageValue, leds.b=averageValue;
  }
  FastSPI_LED.show();

PaulS

Code: [Select]
leds.r = averageValue, leds.g = averageValue, leds.b=averageValue;
I seriously doubt that this code is doing what you think it is. The comma operator is just about the most abused operator that C has. And, you are abusing it.

joeedel89

Then its taking a beating : ) the code seems to work fine; responds like intended.  There was actually a typo in my last post that particular line really looks like
Code: [Select]

leds[i].r = averageLevel, leds[i].g = averageLevel, leds[i].b=averageLevel;


im using the FastSPI library to control an RGB light strip, all 3 colors at the same level create a white light the sensor value just dims.  I am open to other methods if you have any, criticism by itself doesn't help anyone.


PaulS

Quote
There was actually a typo in my last post that particular line really looks like

Those commas are SUPPOSED to be semicolons. Quit abusing the comma operator. Sooner or later, it WILL bite you in the ass.

PeterH


Code: [Select]
leds.r = averageValue, leds.g = averageValue, leds.b=averageValue;
I seriously doubt that this code is doing what you think it is.


It's unconventional and not IMO a good construct to use in this situation, but since the value of the expression is unused I would expect that to have the effect of making three assignments. I'd be surprised if that wasn't what the author expected.

And it's a mistake, which the author should correct now and make a mental note not to repeat. This sort of thing where you use the wrong construct which works by coincidence is very poor practice and WILL bite you on the arse.

You solution is not quite right according to your original post - you should be mapping between 10-60 not 0-60. The only way for the output of that map to exceed 255 is for the input to exceed 60. Is that likely?

Why are you assigning the same value to the LEDs ten times? Have you got one of those dodgy Arduinos where variable assignments sometimes don't work?
I only provide help via the forum - please do not contact me for private consultancy.

AWOL

Quote
Why are you assigning the same value to the LEDs ten times? Have you got one of those dodgy Arduinos where variable assignments sometimes don't work?

No, but another excellent illustration why we should always use CODE TAGS when posting code.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

joeedel89

Quote
You solution is not quite right according to your original post - you should be mapping between 10-60 not 0-60. The only way for the output of that map to exceed 255 is for the input to exceed 60. Is that likely?
My mistake , yes the mapping should go between 10 and 60.  The limit may exceed 60 so I just put an if statement to keep it at 60.
Quote
Why are you assigning the same value to the LEDs ten times? Have you got one of those dodgy Arduinos where variable assignments sometimes don't work?
each led on the strip has a numerical assignment 0,1,2,3 etc.. thats a loop that assigns each LED to act the same.  I posted the full code below in case anyone was interested... this is the first day hour number 3 that I've worked with this stuff so don't expect perfection.

Code: [Select]

int sensorPin = 0;

// an array to hold a bunch of sensor values for an average
int sampleSize = 40; // n readings 0 .. (n - 1)
int sensorReadings[39]; // n readings
int sampleCount = 0;
long sensorValue;

#include <FastSPI_LED.h>

#define NUM_LEDS 32

// Sometimes chipsets wire in a backwards sort of way
struct CRGB { unsigned char b; unsigned char r; unsigned char g; };
// struct CRGB { unsigned char r; unsigned char g; unsigned char b; };
struct CRGB *leds;

#define PIN 4

void setup()
{
  Serial.begin(9600);
  // set our inital setPoint to something
  int setPoint = 50;
 
  // init out our sensorReadings array
  int i;
  for (i = 0; i < sampleSize; i++) {
    sensorReadings[i] = setPoint;
  }
    FastSPI_LED.setLeds(NUM_LEDS);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_TM1809);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_HL1606);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_595);
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);

  FastSPI_LED.setPin(PIN);
  FastSPI_LED.setDataRate(3);
  FastSPI_LED.init();
  FastSPI_LED.start();

  leds = (struct CRGB*)FastSPI_LED.getRGBData();
}

void loop() {
delay (20);
 
  sensorValue = analogRead(sensorPin);
 
  // store the current value in our readings array
  sensorReadings[sampleCount] = sensorValue;
 
  // sampleCount starts life at 0, then loops through sampleSize
  if (sampleCount == sampleSize) {
    sampleCount = 0;
  } else {
    sampleCount++;
  }
 
  // figure out the average sensor value
  int i;
  int sensorSum = 0;
  int averageValue = 0;
  int averageLevel = 0;
  for (i = 0; i < sampleSize; i++) {
    sensorSum = sensorSum + sensorReadings[i];
  }
  averageValue = sensorSum / sampleSize;
  Serial.println(averageValue);
  averageLevel = map(averageValue,12,49,0,255); // as I move the sensor the min/max values change so that is why they aren't consistent with the questions earlier.
  Serial.println(averageLevel);
 
  for(int i = 0; i < 10; i++ ) {

  leds[i].r = averageLevel, leds[i].g = averageLevel, leds[i].b=averageLevel;

  }
  FastSPI_LED.show();
}




PeterH


this is the first day hour number 3 that I've worked with this stuff so don't expect perfection.


I don't expect perfection, but you're still ignoring this problem which has been pointed out repeatedly:
Code: [Select]

  leds[i].r = averageLevel, leds[i].g = averageLevel, leds[i].b=averageLevel;

Should be:
Code: [Select]

  leds[i].r = averageLevel; leds[i].g = averageLevel; leds[i].b=averageLevel;

I only provide help via the forum - please do not contact me for private consultancy.

joeedel89

le fixed

Code: [Select]


int sensorPin = 0;

// an array to hold a bunch of sensor values for an average
int sampleSize = 40; // n readings 0 .. (n - 1)
int sensorReadings[39]; // n readings
int sampleCount = 0;
long sensorValue;

#include <FastSPI_LED.h>

#define NUM_LEDS 32

// Sometimes chipsets wire in a backwards sort of way
struct CRGB { unsigned char b; unsigned char r; unsigned char g; };
// struct CRGB { unsigned char r; unsigned char g; unsigned char b; };
struct CRGB *leds;

#define PIN 4

void setup()
{
  Serial.begin(9600);
  // set our inital setPoint to something
  int setPoint = 50;
 
  // init out our sensorReadings array
  int i;
  for (i = 0; i < sampleSize; i++) {
    sensorReadings[i] = setPoint;
  }
    FastSPI_LED.setLeds(NUM_LEDS);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_TM1809);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_HL1606);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_595);
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);

  FastSPI_LED.setPin(PIN);
  FastSPI_LED.setDataRate(3);
  FastSPI_LED.init();
  FastSPI_LED.start();

  leds = (struct CRGB*)FastSPI_LED.getRGBData();
}

void loop() {
delay (20);
 
  sensorValue = analogRead(sensorPin);
 
  // store the current value in our readings array
  sensorReadings[sampleCount] = sensorValue;
 
  // sampleCount starts life at 0, then loops through sampleSize
  if (sampleCount == sampleSize) {
    sampleCount = 0;
  } else {
    sampleCount++;
  }
 
  // figure out the average sensor value
  int i;
  int sensorSum = 0;
  int averageValue = 0;
  int averageLevel = 0;
  for (i = 0; i < sampleSize; i++) {
    sensorSum = sensorSum + sensorReadings[i];
  }
  averageValue = sensorSum / sampleSize;
  Serial.println(averageValue);
  averageLevel = map(averageValue,12,49,0,255);
  Serial.println(averageLevel);
 
  for(int i = 0; i < 10; i++ ) {

  leds[i].r = averageLevel; leds[i].g = averageLevel; leds[i].b=averageLevel;
  }
  FastSPI_LED.show();
}


PaulS

Consistency is a good habit to develop early.
Code: [Select]
  int i;
  for (i = 0; i < sampleSize; i++) {

  int i;
  for (i = 0; i < sampleSize; i++) {

  for(int i = 0; i < 10; i++ ) {

For the record, I prefer the last version, with the declaration of i INSIDE the statement.

Code: [Select]
  leds[i].r = averageLevel; leds[i].g = averageLevel; leds[i].b=averageLevel;
I also prefer ONE statement per line.

joeedel89

I appreciate the help and best practices, looking forward to contributing some day.

Go Up