Hello all. I'm stumped with a problem due to lack of relevant knowledge and humbly come looking for assistance.
I have fabricated a custom PCB using the TTP229 capacitive touch IC. The device is a 16 step sequencer that will send MIDI eventually once I've figures out the current issue. I'm using an Arduino Nano. There are 16 capacitive touch pads and 16 neopixel LEDs arranged in a circle. The code below is based on the example given here Instruction: One or more 16-key capacitive keypads with Arduino Uno & SPI - #2 by Andreas_Gaunitz
The order in which the 16 electrodes are connected to the IC is different to the order in which the chip delivers the 16 bit integer value, and I want to re-order this somehow. I have a spreadsheet with a comparison of the values as they relate to the chip pins, the readings in the serial monitor and the interface layout.
The code below works in as far as I can read the states of the touch pads, and turn on leds that relate to how many times each pad has been pressed, they're just not in the right order (for instance, pressing electrode 5 turns on LED 1). I've re-ordered the 16 leds to light in the correct orientation using an array, and tried something similar in using a for loop to iterate through an array with the correct ordering of the touch pads, but it doesn't work (it's commented out but the array int buttonOrder[]).
From looking around the forum I now believe that I have to do some bit operations to reorder the values, but it's hurting my brain. Example topic: A better way to do my bit reordering? - #5 by graynomad
My current code:
#include <SPI.h>
const uint8_t MUX_A = 5; // Used to select mux data channel
const uint8_t MUX_B = 6;
uint16_t key_map_8229_0; // The scanned keys
uint16_t key_map_8229_1;
int stepNum[16];
#include <Adafruit_NeoPixel.h>
#define LED_PIN 4
#define LED_COUNT 16
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
unsigned long pixelPrevious = 0; // Previous Pixel Millis
unsigned long patternPrevious = 0; // Previous Pattern Millis
int patternCurrent = 0; // Current Pattern Number
int patternInterval = 5000; // Pattern Interval (ms)
int pixelInterval = 50; // Pixel Interval (ms)
int pixelQueue = 0; // Pattern Pixel Queue
int pixelCycle = 0; // Pattern Pixel Cycle
uint16_t pixelCurrent = 0; // Pattern Current Pixel Number
uint16_t pixelNumber = LED_COUNT; // Total Number of Pixels
const long interval = 400; // interval at which to blink (milliseconds)
int count = -1;
int ledOrder[16] ={ 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5 }; // fixing layout of leds. First led in the chain is
//in position 13 in relation the touchPCB, and are also running anti-clockwise so this fixes that issue
// Variables will change:
int buttonPushCounter[16]; // counter for the number of button presses
int buttonOrder[16];// = { 12, 13, 14, 15, 0, 2, 3, 1, 7, 6, 5, 4, 8, 11, 10, 9 };
int buttonState[16]; // current state of the button
int lastButtonState[16]; // previous state of the button
unsigned long previousMillis = 0; // will store last time LED was updated
// setup() function -- runs once at startup --------------------------------
void setup() {
pinMode(MUX_A, OUTPUT);
pinMode(MUX_B, OUTPUT);
Serial.begin(115200);
SPI.begin();
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE3));
delay(500); // Allow 500ms for the 8229BSF to get ready after turn-on
// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
// Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
// END of Trinket-specific code.
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}
// loop() function -- runs repeatedly as long as board is on ---------------
void loop() {
spi_scan_8229_0(); // Get data frpm the Keypads
spi_scan_8229_1();
//startStop = 0;
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
count++;
strip.setPixelColor(ledOrder[count], strip.Color(150, 150, 150));
strip.show();
if (buttonPushCounter[ledOrder[count]] == 0) {
// strip.setPixelColor(count - 1, strip.Color(0, 0, 0));
strip.show();
}
if (count >= 15) {
count = -1;
}
}
for (int i = 0; i <= 15; i++) {
buttonState[i] = bitRead(key_map_8229_0, i);
//the above reads the 16 bit number into sequencial chunks from first bit to 16th bit.
//the order of this does not relate to the
//this needs to be re-ordered as the physical position of the touch pads isn't correct in relation to the reading
//Serial.println(buttonOrder[i]);
//delay(100);
if (buttonState[i] != lastButtonState[i]) {
// if the state has changed, increment the counter
if (buttonState[i] == 0) {
// if the current state is HIGH then the button went from off to on:
buttonPushCounter[i]++;
Serial.println("button number ");
Serial.print(i);
Serial.print("number of button pushes: ");
Serial.println(buttonPushCounter[i]);
}
}
// save the current state as the last state, for next time through the loop
lastButtonState[i] = buttonState[i];
if (buttonPushCounter[i] == 0) {
strip.setPixelColor(ledOrder[i], strip.Color(0, 0, 0));
strip.show();
}
if (buttonPushCounter[i] == 1) {
strip.setPixelColor(ledOrder[i], strip.Color(0, 150, 0));
strip.show();
}
if (buttonPushCounter[i] == 2) {
strip.setPixelColor(ledOrder[i], strip.Color(0, 0, 150));
strip.show();
}
if (buttonPushCounter[i] == 3) {
strip.setPixelColor(ledOrder[i], strip.Color(150, 0, 0));
strip.show();
}
if (buttonPushCounter[i] == 4) {
buttonPushCounter[i] = 0;
}
}
// set the LED with the ledState of the variable:
//digitalWrite(ledPin, sequence[count]);
// if (startStop == 1) {
// if (sequence[count] == 1) {
// usbMIDI.sendNoteOn(60, 99, channel);
// }
// if (sequence[count] == 0) {
// usbMIDI.sendNoteOff(60, 0, channel); // 60 = C4
// }
// }
}
void spi_scan_8229_0() {
// Select MUX channel for 8229_0
digitalWrite(MUX_A, 0);
digitalWrite(MUX_B, 0);
// Get state of all the keys as a 16 bit integer
key_map_8229_0 = SPI.transfer16(0);
}
void spi_scan_8229_1() {
// Select MUX channel for 8229_1
digitalWrite(MUX_A, 1);
digitalWrite(MUX_B, 0);
// Get state of all the keys as a 16 bit integer
key_map_8229_1 = SPI.transfer16(0);
}