Neopixel and MPR121 programming issues

Hello,

I apologize for my English level, and my programming level.

I have some problems with my project. I've connected an MPR121, neopixels and an arduino nano for a lamp. The general idea is to be able to either have a static light by modifying the luminosity or some dynamic effects (fire, rainbow ...) by pressing one of the inputs of the MPR121.

I tried with the "switch" function which works on static lights but blocks on dynamic effects, and I don't have 12 dospinible pins

// MPR121 initialization
#include <Wire.h>
#include "Adafruit_MPR121.h"

#ifndef _BV
#define _BV(bit) (1 << (bit)) 
#endif

Adafruit_MPR121 cap = Adafruit_MPR121();

// Neopixel initialization
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h>
#endif

uint16_t lasttouched = 0;
uint16_t currtouched = 0;



#define LED_PIN 6 //Led for the column
#define LED_COUNT 47 //Led for the column
#define BRIGHTNESS 255



Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800);




void setup() {


  Serial.begin(9600);

  while (!Serial) { // needed to keep leonardo/micro from starting too fast!
    delay(10);
  }
  
  Serial.println("Adafruit MPR121 Capacitive Touch sensor test"); 
  
  // Default address is 0x5A, if tied to 3.3V its 0x5B
  // If tied to SDA its 0x5C and if SCL then 0x5D
  if (!cap.begin(0x5A)) {
    Serial.println("MPR121 not found, check wiring?");
    while (1);
  }
  Serial.println("MPR121 found!");


  
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif


  strip.begin();
  strip.show();
  strip.setBrightness(BRIGHTNESS);

}



void loop() {

  currtouched = cap.touched();

  switch (currtouched) {

  case 1:
    Fire(55,120,15);
    break;

  case 2:
    colorWipe(strip.Color(0,   0,   0, 170));
    break;

  case 3:
    colorWipe(strip.Color(0,   0,   0, 255));
    break;

  case 4:
    colorWipe(strip.Color(255,   0,   0,  0));
    break;

  case 5:
    colorWipe(strip.Color(0,   255,   0,  0));
    break;

   case 11:
    Serial.print("touched");
    break;
    
   default:
    currtouched = lasttouched;
    break;
  }
  
  return;

}




void colorWipe(uint32_t color) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
  }
}


/* From https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectFire */

void setPixel(int Pixel, byte red, byte green, byte blue, byte white) {
// #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue, white));
// #endif
// #ifndef <Adafruit_NeoPixel.h>

}

void setAll(byte red, byte green, byte blue, byte white) {
  for(int i = 0; i < LED_COUNT; i++ ) {
    setPixel(i, red, green, blue, white);
  }
  strip.show();
}

void Fire(int Cooling, int Sparking, int SpeedDelay) {
  static byte heat[LED_COUNT];
  int cooldown;
 
  // Step 1.  Cool down every cell a little
  for( int i = 0; i < LED_COUNT; i++) {
    cooldown = random(0, ((Cooling * 10) / LED_COUNT) + 2);
   
    if(cooldown>heat[i]) {
      heat[i]=0;
    } else {
      heat[i]=heat[i]-cooldown;
    }
  }
 
  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for( int k= LED_COUNT - 1; k >= 2; k--) {
    heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
  }
   
  // Step 3.  Randomly ignite new 'sparks' near the bottom
  if( random(255) < Sparking ) {
    int y = random(7);
    heat[y] = heat[y] + random(160,255);
    //heat[y] = random(160,255);
  }

  // Step 4.  Convert heat to LED colors
  for( int j = 0; j < LED_COUNT; j++) {
    setPixelHeatColor(j, heat[j] );
  }

  strip.show();
  delay(SpeedDelay);
}

void setPixelHeatColor (int Pixel, byte temperature) {
  // Scale 'heat' down from 0-255 to 0-191
  byte t192 = round((temperature/255.0)*191);
 
  // calculate ramp up from
  byte heatramp = t192 & 0x3F; // 0..63
  heatramp <<= 2; // scale up to 0..252
 
  // figure out which third of the spectrum we're in:
  if( t192 > 0x80) {                     // hottest
    setPixel(Pixel, 255, 255, heatramp, 0);
  } else if( t192 > 0x40 ) {             // middle
    setPixel(Pixel, 255, heatramp, 0, 0);
  } else {                               // coolest
    setPixel(Pixel, heatramp, 0, 0, 0);
  }
}

I tried with "if ... else" but the program directly launches the first effect and I cannot change it.

void loop() {

  currtouched = cap.touched();

  if (currtouched = 1) {
     Fire(55,120,15);
  }

  else if (currtouched = 2) {
    colorWipe(strip.Color(0,0,0,255));
  }

  else {
    currtouched = lasttouched;
  }
  
  return;

}

Thank you in advance for your ideas and advices.

Welcome to the forum.

You need to test both in separate test-sketches.
Do you have the Adafruit MPR121 module ? Because the MPR121 is a 3.3V chip.
Make a sketch to test all the 12 inputs. Show to the Serial Monitor which one is pressed.
Which Arduino board do yo have ?
How do you power the ledstrip ?
With 47 leds, you might need a power supply of 3A. When you power it with a USB cable, then you have less than 500mA available.

1 Like

Thanks for the answer.

I've tried each fonction in seperate sketches without any problem for fonctions and MRP121 inputs.
Yes, it's the adafruit MPR121 but the last version with de converter 3.3V/5V.
I use the classic arduino nano.
Leds are powered by a 3A/5V power supply.

I think the problem come from the code I use in the void loop... but I don't know why =)

Not:

if (currtouched = 1) {

But:

if (currtouched == 1) {
2 Likes

Thanks,

I've tried and it find me the others pins, but the "fire" fonction stop when I relased the pin.

This is the Adafruit MPR121 library: https://github.com/adafruit/Adafruit_MPR121. There is a tutorial for it.
It seems that the function cap.touched returns a bit pattern for all the 12 inputs and it is active as long as that input is touched.

If you want to detect the moment that a key is pressed, or a number of that key, than you have to put that in the sketch.

Can you show a sketch that detects the moment a key is pressed (it is in the example MPR121test.ino) and that converts it to a number and that works for all 12 inputs ?

Is your ledstrip one long ledstrip of 47 leds ?

Do you want to run the Fire function over and over again ? Then you might assign one of the 12 inputs to the command to turn everything off.
You can't use the same variable for the inputs and for the switch-case. You need an overall variable that sets the 'state' of the led pattern.

So you have two parts in the loop() and two variables. I hope this makes sense:

int state = 0;  // start with the 'idle' state for the led pattern

void loop() {

  // ------------------------------------------------------------------------
  // First part of the loop()
  // Check if a input was just pressed and convert the bit pattern
  // into a normal integer for the pressed input (1...12).
  // ------------------------------------------------------------------------
  currtouched = cap.touched();
  // detect if it was just pressed
  ...
  // convert the bit pattern to a key
  ...
  if (key == 12) {
    // special key, clear everything and go to idle
    strip.clear();
    strip.show();
    state = 0;  // idle state
  } else {
    // Only set the new state if everything is okay
    state = key;
  }

  // ------------------------------------------------------------------------
  // Second part of the loop()
  // Run the pattern for the leds according to the 'state' of the led pattern
  // ------------------------------------------------------------------------
  switch (state)  // the 'state' variable selects the led pattern
  {
    case 0:
      // Do nothing.
      // It is always good to have a 'idle' state.
      break;
    case 1:
      Fire(55, 120, 15);
      break;
    ...
  }
}

It will work as a 47 ledstrip ( it's 3 neopixels rings connected in series).

Yes, until an other input is touched.

Yes, one input will turn leds off. There will be others effects but it was to try =)

I understand the logic for the 2 parts, but I have trouble defining the "key", Do i have to link it to " currtouched" or at least define it as integrer?

Thanks, it's work fine

void loop() {

  if (cap.touched() & (1 << 4)) {
    state = 1;
  }
  else if (cap.touched() & (1 << 3)) {
    state = 2;
  }
    else if (cap.touched() & (1 << 2)) {
    state = 0;
  }
  // ------------------------------------------------------------------------
  // Second part of the loop()
  // Run the pattern for the leds according to the 'state' of the led pattern
  // ------------------------------------------------------------------------
  switch (state)  // the 'state' variable selects the led pattern
  {
    case 0:
    strip.clear();
    strip.show();
      break;
    case 1:
      Fire(55, 120, 15);
      break;
     case 2:
      colorWipe(strip.Color(0,   0,   0, 170));
      break;
 
  }
  
  return;

}