1

I'm trying to use a 4x3 matrix keypad as a user interface to control parameters of a Neopixel strip control program.

I'm using Adafruit's Neopixel library and This Keypad library. Both work fine on their own and none of my code, outside this instantiation of the keypad library, interferes with the programs functionality.

The code is around 400 lines so I'm only including a snippet: I've now included all functions which are called in setup, as well as the one we are supposed to land on in loop() as a result of the switch statement.

#include "math.h"
#include "Adafruit_NeoPixel.h"
#include "Keypad.h"
#ifdef __AVR__
#include "avr/power.h"
#endif

#define PIN 9 //Neopixel data pin
#define NUMPIXELS 300 //currently 300

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
    {'1','2','3'},
    {'4','5','6'},
    {'7','8','9'},
    {'*','0','#'}
};

byte rowPins[ROWS] = {8, 7, 6, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {4, 3, 2}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

//f=1/p period should be between 1s and 10s so...
//frequencies should be somewhere between 0.1Hz and 1Hz
int period[NUMPIXELS];

float twoPI = 2 * PI;

int rainbowNow = 0;
unsigned int xOff = 0;

int switcha = 0;

byte hue = 192;
float sat = 0;
float lum = 1;

float lumSave;

int *rgb;

char select = '5';
char hueInc = '6';
char hueDec = '4';
char lumInc = '2';
char lumDec = '8';
char satInc = '3';
char satDec = '1';
char onoff = '0';

boolean holdFlag = 0;

void setup(void) {
  //create array of period lengths for each pixels sine wave
  randomSeed(10);
  for (int i = 0; i < NUMPIXELS; i++) {
    period[i] = random(2, 20);
  }
  Serial.begin(9600);

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  //showOff();
  fadeIn();
  sparkle();
}

void loop(void) {

  char key = keypad.getKey();  
  change(key);

  switch(switcha) {
    case 0: solidColour(); break;
    case 1: rainbow(); break;
    case 2: twinkle(); break;
    case 3: satSine(); break;
    case 4: hueSine(); break;
    case 5: rainbowCycle(); break;
  }
}

void solidColour() {
  rgb = Wheel(hue, sat, lum);
  for(int i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(rgb[0], rgb[1], rgb[2]));
  }
  strip.show();
  delay(20);
}

void fadeIn() {
  Serial.println("FADE IN");
  for(float j=0; j<1; j+=0.16) {
    rgb = Wheel(hue, sat, j);
    for(int i=0; i<NUMPIXELS; i++) {
      strip.setPixelColor(i, strip.Color(rgb[0], rgb[1], rgb[2]));
    }
    strip.show();
    delay(100);
  }
}

void sparkle() {
  Serial.println("SPARKLE");
  rgb = Wheel(hue, sat, lum);
  strip.setPixelColor(0, strip.Color(rgb[0], rgb[1], rgb[2]));
  for(int i=1; i<NUMPIXELS; i++) {
    int blnk = random(0, NUMPIXELS-1);
    strip.setPixelColor(blnk, strip.Color(0, 0, 0));
    strip.show();
    delay(40);
    strip.setPixelColor(blnk, strip.Color(rgb[0], rgb[1], rgb[2]));
    strip.show();
  }
}

//will create pseudo-Saturation by reducing white with increasing sat
//brightness will be achieved by scaling all by a constant
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
int* Wheel(byte WheelPos, float pseudoSat, float pseudoLum) {
  static int rgb[3];
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    rgb[0] = (255 - WheelPos * 3) * pseudoLum;
    rgb[1] = 0;
    rgb[2] = (WheelPos * 3) * pseudoLum;
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    rgb[0] = 0;
    rgb[1] = (WheelPos * 3) * pseudoLum;
    rgb[2] = (255 - WheelPos * 3) * pseudoLum;
  } else if(WheelPos >= 170) {
    WheelPos -= 170;
    rgb[0] = (WheelPos * 3) * pseudoLum;
    rgb[1] = (255 - WheelPos * 3) * pseudoLum;
    rgb[2] = 0;
  }

  return rgb;
}

void change(char key) {
  if(key == select) { //select
    if(switcha < 5) {
      switcha++;
    } else {
      switcha = 0;
    }
  } else if(key == hueDec) { //fwd
    if(hue > 0) {
      hue--;
    } else {
      hue = 255;
    }
  } else if(key == hueInc) { //back
    if(hue < 255) {
      hue++;
    } else {
      hue = 0;
    }
  } else if(key == lumInc) { //up
    if(lum < 1) {
      lum+=0.05;
    } else {
      lum = 0.05;
    }
  } else if(key == lumDec) { //down
    if(lum > 0.05) {
      lum-=0.05;
    } else {
      lum = 1;
    }
  } else if(key == onoff) {
    if(lum != 0) {
      lumSave = lum;
      lum = 0;
    } else if(lum == 0) {
      lum = lumSave;
    }
   } else if(key == satInc) { //play
    if(sat < 1) {
      sat+=0.025;
    } else {
      sat = 0.025;
    }
  } else if(key == satDec) {
    if(sat > 0.025) {
      sat-=0.025;
    } else {
      sat = 1;
    }
  }
}

So long as I comment out the line Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );, the code runs as expected and the Neopixel strip lights up in the way I have programmed. However, with that line, nothing lights up at all. The code still reaches all the functions, (I have checked with Serial.print).

(EDIT: It also works with the Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); included so long as I comment out the switch statement in loop(). How can a statement in loop affect the setup function?!)

I think it must have something to do with either interrupts, or a polling frequency within the Keypad library with interferes with the 'delicate' timing of the Neopixels.

The massively frustrating this is that I have solved this problem before on this exact hardware but the code was lost and I'm having to reconstruct it for a repair job.

If you could help me specifically identify the problem, or suggest how I might implement my keypad interface with the neopixels I would be very grateful.

Arduino ide2:1.0.5 (EDIT: also used 1.8.9 with no different result)

Arduino Nano Board

Sodial 4x3 Matrix Keypad

ws2812b rgb 300 neopixel 5M strip

4
  • Are you saying IDE version 1.0.5? That is ancient. Upgrade to something current. I think 1.8.9 is the latest. www.arduino.cc
    – CrossRoads
    May 7 '19 at 16:59
  • 1
    The used keypad library doesn't use interrupts, so the problem must lie at another place. Please create a short working example, that shows your problem, so that we can see the whole code, that isn't working. That is better than cutting parts of the code out.
    – chrisl
    May 7 '19 at 17:30
  • I've added the extra functions to make it (should be) working code. Lights fade in, lights blink, lights go solid colour. Hope that gives you more context. May 8 '19 at 17:23
  • In some cycles you iterate to NUMPIXELS. In some - to strip.numPixels(). Why the discrepancy? Are they the same?
    – AnT
    May 8 '19 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.