Macropad weird behaviour

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
sashaT
 
Posts: 45
Joined: Thu Dec 24, 2020 1:06 pm

Macropad weird behaviour

Post by sashaT »

Hi all, I just received the Adabox019, and I installed the arduino core from https://learn.adafruit.com/adafruit-mac ... 40/arduino, and it worked fine. I uploaded the example sketch, and the lights went on. I then uploaded another sketch that is supposed to work (example sketch from Adafruit) and then everything turned off, and the display showed the Adafruit logo when it was not supposed to. Whenever I double click the reset, the drive pops up, showing RPI-RP2, but Arduino IDE does not recognize any ports. When I click it once, the drive goes away and I see in the Com ports 'COM15 (Raspberry pi pico)'). But then I try to upload the original sketch (that worked fine), and it either throws an error 'No drive to write to' or uploads fine and then the MacroPad does nothing. Occasionally I get an Adafruit logo, but I assume that is a default 'bricked' message. I tried downloading CircuitPython and it works fine. I tried storage.erasefilesystem() but it just hangs there forever. Please help!

Thanks

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

Re: Macropad weird behaviour

Post by mikeysklar »

What was the 'first' sketch that worked and the 'second' example sketch we provide where the problems seemed to start up? I understand that they were both Arduino IDE based uploads. I wanted to check them out and see what might have happened.

The RP2040 based boards should bring you into bootloader mode when you press the reset button combined with the boot button. In the case of the macropad the rotary encoder (dial) can be pressed down and that is the boot button.

https://learn.adafruit.com/adafruit-mac ... 40/pinouts

https://learn.adafruit.com/adafruit-mac ... -3098867-7
We snuck the BOOT button in as the button switch in the rotary encoder. Press the rotary encoder to engage the BOOT button!

User avatar
sashaT
 
Posts: 45
Joined: Thu Dec 24, 2020 1:06 pm

Re: Macropad weird behaviour

Post by sashaT »

Hi! Thank you for the fast reply. The first one that worked was this one:

Code: Select all

void setup() {
  Serial.begin(115200);
  delay(5000);
}

void loop() {
  Serial.printf("Core temperature: %2.1fC\n", analogReadTemp());
  delay(1000);
}
Then, I uploaded this, with all the variables replaced with their respective pins, and this worked,

Code: Select all

#include <Adafruit_SH110X.h>
#include <Adafruit_NeoPixel.h>
#include <RotaryEncoder.h>
#include <Wire.h>

// Create the neopixel strip with the built in definitions NUM_NEOPIXEL and PIN_NEOPIXEL
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(12, 19, NEO_GRB + NEO_KHZ800);

// Create the OLED display
Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &SPI1, 24, 23, 22);

// Create the rotary encoder
RotaryEncoder encoder(17, 18, RotaryEncoder::LatchMode::FOUR3);
void checkPosition() {  encoder.tick(); } // just call tick() to check the state.
// our encoder position state
int encoder_pos = 0;

void setup() {
  Serial.begin(115200);
  //while (!Serial) { delay(10); }     // wait till serial port is opened
  delay(100);  // RP2040 delay is not a bad idea

  Serial.println("Adafruit Macropad with RP2040");

  // start pixels!
  pixels.begin();
  pixels.setBrightness(255);
  pixels.show(); // Initialize all pixels to 'off'

  // Start OLED
  display.begin(0, true); // we dont use the i2c address but we will reset!
  display.display();
  
  // set all mechanical keys to inputs
  for (uint8_t i=0; i<=12; i++) {
    pinMode(i, INPUT_PULLUP);
  }



  // set rotary encoder inputs and interrupts
  pinMode(17, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(17), checkPosition, CHANGE);
  attachInterrupt(digitalPinToInterrupt(18), checkPosition, CHANGE);  

  // We will use I2C for scanning the Stemma QT port
  Wire.begin();

  // text display tests
  display.setTextSize(1);
  display.setTextWrap(false);
  display.setTextColor(SH110X_WHITE, SH110X_BLACK); // white text, black background
/*
  pinMode(16, OUTPUT);
  digitalWrite(16, LOW);
  tone(16, 988, 100);  // tone1 - B5
  delay(100);
 tone(16, 1319, 200); // tone2 - E6
   delay(200)
   */
}

uint8_t j = 0;
bool i2c_found[128] = {false};

void loop() {
  display.clearDisplay();
  display.setCursor(0,0);
  display.println("* Adafruit Macropad *");
  
  encoder.tick();          // check the encoder
  int newPos = encoder.getPosition();
  if (encoder_pos != newPos) {
    Serial.print("Encoder:");
    Serial.print(newPos);
    Serial.print(" Direction:");
    Serial.println((int)(encoder.getDirection()));
    encoder_pos = newPos;
  }
  display.setCursor(0, 8);
  display.print("Rotary encoder: ");
  display.print(encoder_pos);

  // Scanning takes a while so we don't do it all the time
  if ((j & 0x3F) == 0) {
    Serial.println("Scanning I2C: ");
    Serial.print("Found I2C address 0x");
    for (uint8_t address = 0; address <= 0x7F; address++) {
      Wire.beginTransmission(address);
      i2c_found[address] = (Wire.endTransmission () == 0);
      if (i2c_found[address]) {
        Serial.print("0x");
        Serial.print(address, HEX);
        Serial.print(", ");
      }
    }
    Serial.println();
  }
  
  display.setCursor(0, 16);
  display.print("I2C Scan: ");
  for (uint8_t address=0; address <= 0x7F; address++) {
    if (!i2c_found[address]) continue;
    display.print("0x");
    display.print(address, HEX);
    display.print(" ");
  }
  
  // check encoder press
  display.setCursor(0, 24);
  if (!digitalRead(0)) {
    Serial.println("Encoder button");
    display.print("Encoder pressed ");
    pixels.setBrightness(255);     // bright!
  } else {
    pixels.setBrightness(80);
  }

  for(int i=0; i< pixels.numPixels(); i++) {
    pixels.setPixelColor(i, Wheel(((i * 256 / pixels.numPixels()) + j) & 255));
  }
  
  for (int i=1; i<=12; i++) {
    if (!digitalRead(i)) { // switch pressed!
      Serial.print("Switch "); Serial.println(i);
      pixels.setPixelColor(i-1, 0xFFFFFF);  // make white
      // move the text into a 3x4 grid
      display.setCursor(((i-1) % 3)*48, 32 + ((i-1)/3)*8);
      display.print("KEY");
      display.print(i);
    }
  }

  // show neopixels, incredment swirl
  pixels.show();
  j++;

  // display oled
  display.display();
}





// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
   WheelPos -= 170;
   return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
}
But then THIS bricked it, the same thing except with the Tone functions in the setup uncommented

Code: Select all

#include <Adafruit_SH110X.h>
#include <Adafruit_NeoPixel.h>
#include <RotaryEncoder.h>
#include <Wire.h>

// Create the neopixel strip with the built in definitions NUM_NEOPIXEL and PIN_NEOPIXEL
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(12, 19, NEO_GRB + NEO_KHZ800);

// Create the OLED display
Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &SPI1, 24, 23, 22);

// Create the rotary encoder
RotaryEncoder encoder(17, 18, RotaryEncoder::LatchMode::FOUR3);
void checkPosition() {  encoder.tick(); } // just call tick() to check the state.
// our encoder position state
int encoder_pos = 0;

void setup() {
  Serial.begin(115200);
  //while (!Serial) { delay(10); }     // wait till serial port is opened
  delay(100);  // RP2040 delay is not a bad idea

  Serial.println("Adafruit Macropad with RP2040");

  // start pixels!
  pixels.begin();
  pixels.setBrightness(255);
  pixels.show(); // Initialize all pixels to 'off'

  // Start OLED
  display.begin(0, true); // we dont use the i2c address but we will reset!
  display.display();
  
  // set all mechanical keys to inputs
  for (uint8_t i=0; i<=12; i++) {
    pinMode(i, INPUT_PULLUP);
  }



  // set rotary encoder inputs and interrupts
  pinMode(17, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(17), checkPosition, CHANGE);
  attachInterrupt(digitalPinToInterrupt(18), checkPosition, CHANGE);  

  // We will use I2C for scanning the Stemma QT port
  Wire.begin();

  // text display tests
  display.setTextSize(1);
  display.setTextWrap(false);
  display.setTextColor(SH110X_WHITE, SH110X_BLACK); // white text, black background

  pinMode(16, OUTPUT);
  digitalWrite(16, LOW);
  tone(16, 988, 100);  // tone1 - B5
  delay(100);
 tone(16, 1319, 200); // tone2 - E6
   delay(200)

}

uint8_t j = 0;
bool i2c_found[128] = {false};

void loop() {
  display.clearDisplay();
  display.setCursor(0,0);
  display.println("* Adafruit Macropad *");
  
  encoder.tick();          // check the encoder
  int newPos = encoder.getPosition();
  if (encoder_pos != newPos) {
    Serial.print("Encoder:");
    Serial.print(newPos);
    Serial.print(" Direction:");
    Serial.println((int)(encoder.getDirection()));
    encoder_pos = newPos;
  }
  display.setCursor(0, 8);
  display.print("Rotary encoder: ");
  display.print(encoder_pos);

  // Scanning takes a while so we don't do it all the time
  if ((j & 0x3F) == 0) {
    Serial.println("Scanning I2C: ");
    Serial.print("Found I2C address 0x");
    for (uint8_t address = 0; address <= 0x7F; address++) {
      Wire.beginTransmission(address);
      i2c_found[address] = (Wire.endTransmission () == 0);
      if (i2c_found[address]) {
        Serial.print("0x");
        Serial.print(address, HEX);
        Serial.print(", ");
      }
    }
    Serial.println();
  }
  
  display.setCursor(0, 16);
  display.print("I2C Scan: ");
  for (uint8_t address=0; address <= 0x7F; address++) {
    if (!i2c_found[address]) continue;
    display.print("0x");
    display.print(address, HEX);
    display.print(" ");
  }
  
  // check encoder press
  display.setCursor(0, 24);
  if (!digitalRead(0)) {
    Serial.println("Encoder button");
    display.print("Encoder pressed ");
    pixels.setBrightness(255);     // bright!
  } else {
    pixels.setBrightness(80);
  }

  for(int i=0; i< pixels.numPixels(); i++) {
    pixels.setPixelColor(i, Wheel(((i * 256 / pixels.numPixels()) + j) & 255));
  }
  
  for (int i=1; i<=12; i++) {
    if (!digitalRead(i)) { // switch pressed!
      Serial.print("Switch "); Serial.println(i);
      pixels.setPixelColor(i-1, 0xFFFFFF);  // make white
      // move the text into a 3x4 grid
      display.setCursor(((i-1) % 3)*48, 32 + ((i-1)/3)*8);
      display.print("KEY");
      display.print(i);
    }
  }

  // show neopixels, incredment swirl
  pixels.show();
  j++;

  // display oled
  display.display();
}





// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
   WheelPos -= 170;
   return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
}

I tried uploading it without the tone but the same results.
Also, it takes forever to upload, the final command, uf2conv.py, runs forever and only sometimes finishes.
Thank you!

User avatar
sashaT
 
Posts: 45
Joined: Thu Dec 24, 2020 1:06 pm

Re: Macropad weird behaviour

Post by sashaT »

Also I get errors like this even if I have a com port:
Resetting COM5
Converting to uf2, output size: 161792, start address: 0x2000
No drive to deploy.
An error occurred while uploading the sketch

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

Re: Macropad weird behaviour

Post by mikeysklar »

It looks like you have a usable COM port, but things sound unstable.

Are you on a Windows Machine? Are you using a USB3 adapter or coming off a keyboard plug? The scenario you have described where uploading sort of works, but is prone to failure has the flavor of a underpowered USB port. We are always chasing non-USB data cables, but you clearly have been able to sync over code.

What happens when you put use the BOOT/RESET combo by pushing down on the macropad dial? (not the double click reset you had started with). This dance will likely take several tries to get a feel for.

User avatar
franko553
 
Posts: 4
Joined: Fri Oct 14, 2016 2:21 pm

Re: Macropad weird behaviour

Post by franko553 »

I am having similar challenges with my Macropad. I did some trial and error, and it seems that the NeoPixel show() command does not play nicely with the tone() command when they are too close together. I found that if they are two or more iterations of the main loop apart, or if you put a delay(10) between them, there are no issues. Otherwise, when the tone() command executes, it either does not produce the correct tone or, if the two commands are really too close, the tone() command will lock up and not allow execution to continue. I have not delved too deeply into either the RP2040 internals or the NeoPixel library but I would assume that the two functions are trying to use the same timer and/or peripheral to generate their output which is causing the error.

If you uncomment the tone commands in the setup() function of the example sketch, execution never proceeds to the loop() function at all, giving the Macropad the appearance of locking up with just the Adafruit logo. If you comment out the pixels.show() command a few lines above it in the setup() function, the tone works fine and the NeoPixels initialize later at the end of the loop() function.

I also have to always trigger the bootloader manually when I upload sketches by holding down the encoder button while pressing reset. Annoying, but not the end of the world.

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

Re: Macropad weird behaviour

Post by mikeysklar »

@franko553 - Thank you for the deets of your experience. This is helpful.

NeoPixels disable interrupts when turning on LEDs and tone() needs those interrupts to work. It's an old issue with reports going back to 2013. The best work around would be to manually turn on the NeoPixels with show() and keep those away from tone() calls or do what you suggest and add some delays to spread things out.

Good to know about boot mode being necessary for code upload. That is the way it is on most of our controllers, but the macropad having a pushdown pot is less intuitive.

User avatar
sashaT
 
Posts: 45
Joined: Thu Dec 24, 2020 1:06 pm

Re: Macropad weird behaviour

Post by sashaT »

Sorry for the slow reply! We were camping ;)

When I upload the code WITHOUT the tone(), it is still bricked. Thanks!

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

Re: Macropad weird behaviour

Post by mikeysklar »

sashaT,

Please repost your code with the modifications so we can review for anything else that stands out.

Have you been doing the same boot/reset button combo of pressing down the macropad dial during u/l of the code?

User avatar
RufusVS2020
 
Posts: 62
Joined: Thu Nov 19, 2020 6:31 pm

Re: Macropad weird behaviour

Post by RufusVS2020 »

Similar problem with the tone() function: I got my Adabox today and wanted to drive the speaker. I found two different arduino sources for the demo. One that was shipped had the self-test code in it and a digikey splash screen included, but no speaker code. The other I found had what looked like the start of speaker code that was commented out. I tried to uncomment the code and it would lockup my macropad after the digikey splash came up. I bitbanged the PIN_SPEAKER and PIN_SPEAKER_ENABLE keys and got a sound out of it. I can only conclude that the tone() function is broken in the arduino macropad code. I am going to see if the CircuitPython version fares better.

User avatar
sashaT
 
Posts: 45
Joined: Thu Dec 24, 2020 1:06 pm

Re: Macropad weird behaviour

Post by sashaT »

Ok, it worked, thanks!

Locked
Please be positive and constructive with your questions and comments.

Return to “AdaBox! Show us what you made!”