Issues with Map Function

I am trying to replace some chunky if statements with a Map function. The code compiles without error but renders the Arduino inop. The chunky code works as is, but I would like to make it smother with mapping.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated
// constants won't change:
const long interval = 300000;           // interval at which to wait to re-engage Refrigerator circuit(milliseconds)

const int numReadings = 50;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A0;
int SSR1=9;           // the PWM pin the Water heater SSR is attached to
int SSR2= 8;           // the Digital pin of the Refrigerator Circuit is not PWM
float output = 0;    // how much power the SSR allows through

// the setup routine runs once when you press reset:
void setup() {
  // declare pins 8, 9 to be an output:
  pinMode(SSR1, OUTPUT);
  pinMode(SSR2, OUTPUT);
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(200); // Pause for 0.2 seconds

  // Clear the buffer
  display.clearDisplay();
  
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

// the loop routine runs over and over again forever:
void loop() {
  unsigned long currentMillis = millis();
  
  // set the output of pin 9:
  //analogWrite(SSR1, output);

  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(A0);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = average * (5 / 1023.0)*0.935*5;
  
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(1, 0);
  display.println("VOLTS");
  display.println("OTPT");
  display.setTextSize(2); // Draw 4X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(65, 0);
  display.println (voltage);
  display.setCursor(65, 17);
  display.println (average);  
  display.display();      // Show initial text
  
  display.clearDisplay();
  
  
  //if voltage is less than 13.1 turn SSR1 off
  if (average <580){
    analogWrite(SSR1, 0);
  }
  
  //if voltage is between 13.2 and 13.9 SSR @10%
  if ((average >=580)&& (average <609)){
    analogWrite(SSR1, 26);
  }
  //if voltage is between 13.9 and 14.0 SSR @20%
  if ((average >=609)&& (average <613)){
    analogWrite(SSR1, 51);
  }
   //if voltage is between 14.0 and 14.1 SSR @30%
  if ((average >=613)&& (average <617)){
    analogWrite(SSR1, 77);
  }
  //if voltage is between 14.1 and 14.2 SSR @40%
  if ((average>=617)&& (average <621)){
    analogWrite(SSR1, 102);
  }
  //if voltage is above 14.2 SSR @50%
  if (average>=621){
    analogWrite(SSR1, 128);
  }
  
  // print out the value you read:
  Serial.print (average);
  Serial.print ("     ");
  Serial.print (voltage);
  Serial.println ("  VOLTS");
  
  //if voltage is Greater than 13.1 and timer has reached 5 minutes turn SSR2 on
  if ((average >580)&& (currentMillis - previousMillis >= interval)) {
    digitalWrite(SSR2,HIGH);//Turn on SSR2
    previousMillis = currentMillis; //Reset interval timer to zero
  }  else if (average <=580){
    digitalWrite(SSR2,LOW) ;//if voltage is less than 13.1 and timer has reached 5 minutes turn SSR2 off
    previousMillis = currentMillis; //Reset interval timer to zero
  }
  
  delay (3);
}

The lines I am modifying are 101-124 to read:

//Map average voltages of 13.2-14.2 to SSR1
  {
  average = map(average,580,621,26,128);
  analogWrite(SSR1,average);
  }
  //if voltage is less than 13.1 turn SSR1 off
  if (average <580){
    analogWrite(SSR1, 0);
  }
  
  //if voltage is above 14.2 SSR @50%
  if (average>621){
    analogWrite(SSR1, 128);
  }

What am I doing wrong?

I think there might be a problem with the line numbers you are replacing. I loaded your first script and the replaced 101-124 with the second list and it won't compile.

Please post your complete modified code.

PickyBiker:
I think there might be a problem with the line numbers you are replacing. I loaded your first script and the replaced 101-124 with the second list and it won't compile.

Please post your complete modified code.

Apologies. It was lines 103-127. Regardless, Here is the complete modified code that compiles but won't function.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated
// constants won't change:
const long interval = 300000;           // interval at which to wait to re-engage Refrigerator circuit(milliseconds)

const int numReadings = 50;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A0;
int SSR1=9;           // the PWM pin the Water heater SSR is attached to
int SSR2= 8;           // the Digital pin of the Refrigerator Circuit is not PWM
float output = 0;    // how much power the SSR allows through

// the setup routine runs once when you press reset:
void setup() {
  // declare pins 8, 9 to be an output:
  pinMode(SSR1, OUTPUT);
  pinMode(SSR2, OUTPUT);
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(200); // Pause for 0.2 seconds

  // Clear the buffer
  display.clearDisplay();
  
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

// the loop routine runs over and over again forever:
void loop() {
  unsigned long currentMillis = millis();
  
  // set the output of pin 9:
  //analogWrite(SSR1, output);

  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(A0);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = average * (5 / 1023.0)*0.935*5;
  
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(1, 0);
  display.println("VOLTS");
  display.println("OTPT");
  display.setTextSize(2); // Draw 4X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(65, 0);
  display.println (voltage);
  display.setCursor(65, 17);
  display.println (average);  
  display.display();      // Show initial text
  
  display.clearDisplay();
  //Map average voltages of 13.2-14.2 to SSR1
  {
  average = map(average,578,621,26,128);
  analogWrite(SSR1,average);
  }
  //if voltage is less than 13.21 turn SSR1 off
  if (average <578){
    analogWrite(SSR1, 0);
  }
  
  //if voltage is above 14.2 SSR @50%
  if (average>621){
    analogWrite(SSR1, 128);
  }
  
  // print out the value you read:
  Serial.print (average);
  Serial.print ("     ");
  Serial.print (voltage);
  Serial.println ("  VOLTS");
  
  //if voltage is Greater than 13.1 and timer has reached 1 minute turn SSR2 on
  if ((average >580)&& (currentMillis - previousMillis >= interval)) {
    digitalWrite(SSR2,HIGH);//Turn on SSR2
    previousMillis = currentMillis; //Reset interval timer to zero
  }  else if (average <=580){
    digitalWrite(SSR2,LOW) ;//if voltage is less than 13.1 turn SSR2 off
    previousMillis = currentMillis; //Reset interval timer to zero
  }
  
  delay (3);
}
map(value, fromLow, fromHigh, toLow, toHigh)
  //Map average voltages of 13.2-14.2 to SSR1
  {
  average = map(average,578,621,26,128);
  analogWrite(SSR1,average);
  }
  //if voltage is less than 13.21 turn SSR1 off
  if (average <578){
    analogWrite(SSR1, 0);
  }
 
  //if voltage is above 14.2 SSR @50%
  if (average>621){
    analogWrite(SSR1, 128);
  }

You map the readings to be between 26 and 128, but then try to use the unmapped values in some conditional tests. average is certainly going to be <578 and the SSR1 will be off.

cattledog:

map(value, fromLow, fromHigh, toLow, toHigh)

You map the readings to be between 26 and 128, but then try to use the unmapped values in some conditional tests. average is certainly going to be <578 and the SSR1 will be off.

Yes that is correct, I think. I only want the map function to effect the output to SSR1 in a voltage range of 13.2-14.2V. Within that range I want a smooth output from 0-40%. Below that range I want it totally off and above that range I still only want a maximum output of 40%.
Is there a better way to accomplish this?

Your thinking is correct, but you have not changed the variable name, and it now holds the mapped values. You need to test against the mapped values and not the original ones.

cattledog:
Your thinking is correct, but you have not changed the variable name, and it now holds the mapped values. You need to test against the mapped values and not the original ones.

I think I am starting to track you. So if I add a declaration
"int outPut = 0; // the output mapping"
and then change the loop code to
{
outPut = map(average,578,621,0,128);
analogWrite(SSR1,outPut);
}"
would that give me the effect I'm looking for?

would that give me the effect I'm looking for?

Yes. You may want to look at using constrain() before or after mapping to make sure everything is in range. Otherwise you can get unexpected values from map.

Map does not constrain values to within the range, because out-of-range values are sometimes intended and useful. The constrain() function may be used either before or after this function, if limits to the ranges are desired.

Excellent. Thanks for your help and the link. I'm losing sunlight to keep my voltage up, so testing will have to wait for another day.
Much appreciated!