Why does this code disable boards?

Hi

I'm yet another NON-Programmer trying to cobble things into a working state...

The issue is that when I upload this sketch, I think it kills the board USB port - so that it becomes unusable, ie. the IDE can't see the board or USB port. (I have tried the various tricks to bring a board back to life, but none have worked so far... they will have to wait!).

I have 3 boards which do not work now.

The sketch is for a simple midi control box with 5 knobs, a button and a Trigger input.
Originally the sketch was for 5 knobs and a button - and that works perfectly in an existing unit. The issue started when I tried adding the Trigger input - and then the boards started stopping working completely.

So if a kind soul could possibly spot the issue I would be eternally grateful!

The addition of the Trigger code comes from a different Project Source to the knobs and button, so any suggestions for improving the Trigger code are also very welcome!

Many thanks in advance!

//
//  Copyright Will Hitchings 2024 
//
//     PLUS-4
//     ======
//
//  Sketch for a Midi Box to control a 
//
//        SELF-CONTAINED KICK + SUB SYSTEM
//        ================================
//
//   1x BUTTON SWITCH (D1)
//   1x TRIGGER INPUT  (A5)
//   5x POTENTIOMETERS (A0-1-2-3-4)
//
//    PIN ASSIGNMENTS
//   
//    A0 = POT 1 FREQ           CC01
//    A1 = POT 2 KICK 1         CC02
//    A2 = POT 3 KICK 2         CC03
//    A3 = POT 4 KICK 3         CC04
//    A4 = POT 5 KICK SUB    CC05
//    A5 = TRIGGER INPUT    NOTE 36
//    D1 = BUTTON                NOTE 30
//  
//    MIDI CHANNEL 1
//
//   = = = CHECK 'boards.txt' ! ! !
//

#include "MIDIUSB.h"

// BUTTON + TRIGGER to MIDI Notes
//
#define BTN_NOTE 30 //  BOOM BUTTON
#define TRIG_NOTE 36 //  KICK TRIGGER

#define deviceChannel 0 //   This is the MIDI channel number 0-15
#define buttonDebounceTime 150 //   Debounce time for each button in milliseconds (prevents multiple triggers due to chatter)

const int ButtonPin[1] = {1}; //    BOOM BUTTON
const int TriggerPin[1] = {'A5'}; // KICK TRIGGER


//
//    TRIGGER
//

char pinAssignments[1] = {'A5'};
byte TrigNote[1] = {36};         	// MIDI note
int TrigCutOff[1] = {5};       	// Minimum Analog value to cause a drum hit
int MaxPlayTime[1] = {150};      	// Cycles before a 2nd hit is allowed

boolean VelocityFlag  = true;
boolean activeTrig[1] = {0};             // Array of flags of pad currently playing
int PinPlayTime[1] = {0};               // Counter since pad started to play
byte status1;

int pin = A5;     
int hitavg = 0;


//
//    POTENTIOMETERS
//

const int NPots = 5; //   total number of POTS
const int potPin[NPots] = {A0, A1, A2 , A3, A4}; //   Arduino POT Pins ; Leave nothing in the array if 0 pots {}

int potCState[NPots] = {0}; // Current state of the pot; delete 0 if 0 pots
int potPState[NPots] = {0}; // Previous state of the pot; delete 0 if 0 pots
int potVar = 0; // Difference between the current and previous state of the pot

int midiCState[NPots] = {0}; // Current state of the midi value; delete 0 if 0 pots
int midiPState[NPots] = {0}; // Previous state of the midi value; delete 0 if 0 pots

const int TIMEOUT = 300; //* Amount of time the potentiometer will be read after it exceeds the varThreshold
const int varThreshold = 20; //* Threshold for the potentiometer signal variation
boolean potMoving = true; // If the potentiometer is moving
unsigned long PTime[NPots] = {0}; // Previously stored time; delete 0 if 0 pots
unsigned long timer[NPots] = {0}; // Stores the time that has elapsed since the timer was reset; delete 0 if 0 pots


//
// MIDI Assignments 
//

// byte midiCh = 1; //* MIDI channel to be used
byte note = 30; //* Lowest note to be used; 30 = BOOM BUTTON, 36 = KICK TRIGGER
byte cc = 1; //* Lowest MIDI CC to be used


// --------------------------------------------------------

bool InternalLED_state = LOW;

bool buttonState[1] = {0};
unsigned long buttonToggleTime[1] = {0};

//-----------------------------------------------------
//
// START of SETUP
//

void setup() 
{

    Serial.begin(115200);
//    Serial.println(hitavg);

 
  for    (int i=0; i<1; i++)
  { 
       pinMode(ButtonPin[1], INPUT);   // For All buttons
       pinMode(TriggerPin[A5], INPUT);   // For All buttons

  }

}

//
// END of SETUP
//


//-----------------------------------------------------
//
// START of VOID LOOP
//

void loop() 
{



//
//   TRIGGER
//

{
  for (int pin=A5; pin++;) // pin < 16; pin++) 
// 
  {
    //int pin = 3;
    //   for (pinRead=0; pinRead < 16, pin++){
    hitavg = analogRead(pinAssignments[pin]);  
 //Serial.println(hitavg);   
    // read the input pin

    if((hitavg > TrigCutOff[pin]))
    {
      if((activeTrig[pin] == false))
      {
        if(VelocityFlag == true)
        {
          //          hitavg = 127 / ((1023 - PadCutOff[pin]) / (hitavg - PadCutOff[pin]));    // With full range (Too sensitive ?)
          hitavg = (hitavg / 4) -1 ;                                                 // Upper range
        }
        else
        {
          hitavg = 127;
        }
        //noteOn(144,TrigNote[pin],hitavg); //note on
        noteOn(deviceChannel, TRIG_NOTE, 127); // Channel, Note, Velocity

        PinPlayTime[pin] = 0;
        activeTrig[pin] = true;
      }
      else
      {
        PinPlayTime[pin] = PinPlayTime[pin] + 1;
      }
    }
    else if((activeTrig[pin] == true))
    {
      PinPlayTime[pin] = PinPlayTime[pin] + 1;
      if(PinPlayTime[pin] > MaxPlayTime[pin])
      {
        activeTrig[pin] = false;
        //noteOff(144,TrigNote[pin],,0);
        noteOff(deviceChannel, TRIG_NOTE,0); 
        
      }
    }
  } 
}



//
//   END TRIGGER
//



//
// POTS 
//

potentiometers();

  midiEventPacket_t rx;
  rx = MidiUSB.read(); // Check for Message
  if (rx.header != 0);  // If message Received


//
//     CHECK BUTTON
//

  for (int i=0; i<1; i++){ // ALL BUTTONS
      if (millis() < buttonToggleTime[i] + buttonDebounceTime){ // If it was recently changed
        continue;                                               // Skip this SWITCH. Do next one
      }
    
      if (buttonState[i] == 0){ // If BUTTON is Not Pressed Already 
          if (digitalRead(ButtonPin[i]) == 0){ // Pin is Low, BUTTON is pressed
              buttonState[i] = 1; // Mark as pressed
              buttonToggleTime[i] = millis(); // Update Event Time
              switch(i){  // Pick which Note it is (from BUTTON ID)
                case 0: 
                    noteOff(deviceChannel, BTN_NOTE, 0); // Channel, Note, Velocity
                    break;
                
                 
              } // End CHECK SWITCHES

          } // End SWITCHES Read

      } // End IF (SWITCH Not Already Pressed)
      
      else{ // SWITCH Already Pressed (SWITCH State == 1)
      
          if (digitalRead(ButtonPin[i]) == 1){ // Pin is High, SWITCH is released              
                //toggleOnBoardLED(); // FOR DEBUGGING -  CAN BE REMOVED - WH added ;
                buttonState[i] = 0; // Mark as released
                buttonToggleTime[i] = millis(); // Update Event Time

                //
                // MIDI NOTE OFF MESSAGES FOR SWITCHES
                //
                switch(i){  // Pick which Note it is (from button ID)
                    case 0: 
                        noteOn(deviceChannel, BTN_NOTE, 127); // Channel, Note, Velocity
                        break;

               
                } // End SWITCHES
              
          }// End SWITCHES READ

      } // End ELSE (SWITCH Already Pressed)

      
  }// End IF SWITCHES
  
 
//
}// END of VOID LOOP 
//


//
//-----------------------------------------------------
//


//
// START of FINAL VOID
//

//
//  POTENTIOMETERS
//

void potentiometers() 

{
  for (int i = 0; i < NPots; i++) { // Loops through all the potentiometers

    potCState[i] = analogRead(potPin[i]); // reads the pins from arduino

    midiCState[i] = map(potCState[i], 0, 1023, 0, 200); // Maps the reading of the potCState to a value usable in midi

    potVar = abs(potCState[i] - potPState[i]); // Calculates the absolute value between the difference between the current and previous state of the pot

    if (potVar > varThreshold) { // Opens the gate if the potentiometer variation is greater than the threshold
      PTime[i] = millis(); // Stores the previous time
    }

    timer[i] = millis() - PTime[i]; // Resets the timer 11000 - 11000 = 0ms

    if (timer[i] < TIMEOUT) { // If the timer is less than the maximum allowed time it means that the potentiometer is still moving
      potMoving = true;
    }
    else {
      potMoving = false;
    }

    if (potMoving == true) { // If the potentiometer is still moving, send the change control
      if (midiPState[i] != midiCState[i]) {

        // Sends  MIDI CC 
        // Use if using with ATmega32U4 (micro, pro micro, leonardo...)
        controlChange(deviceChannel, cc + i, midiCState[i]); //  (channel, CC number,  CC value)
        MidiUSB.flush();

        potPState[i] = potCState[i]; // Stores the current reading of the potentiometer to compare with the next
        midiPState[i] = midiCState[i];
      }
    }
  } 
  }// FOR END
//
//    END POTENTIOMETERS

//
void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
  }
//
//
void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
  MidiUSB.flush();// Send note now
  }
//
//
void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
  MidiUSB.flush(); // Send note now
  }

//
// END of FINAL VOID
//

const int ButtonPin[1] = { 1 };      //    BOOM BUTTON

What use is a one dimensional array ?
To add to that, you appear to be using pin 1 as an input but it is used by the Serial interface and to upload code to the board

Do you suppose that could that be a problem ?

1 Like

Start by checking for errors in circuit design, wiring and/or power supply, all of which you forgot to describe.

It is extremely unlikely that code alone can permanently disable an Arduino.

1 Like

Even Will is askung questions...

Looks like you're writing outside the bounds of arrays. Print the value of pin inside the loop.

You did not mention which board as far as I can see!!

I suggest that you set compiler warnings to all under file → preferences in the IDE.

Below demo code results in the following warnings (when compiled for an AVR based board (Mega)).

C:\Users\bugge\AppData\Local\Temp\.arduinoIDE-unsaved2025420-6596-fhro1s.e7a9r\sketch_may20a\sketch_may20a.ino: In function 'setup':
C:\Users\bugge\AppData\Local\Temp\.arduinoIDE-unsaved2025420-6596-fhro1s.e7a9r\sketch_may20a\sketch_may20a.ino:6:25: warning: iteration 32708 invokes undefined behavior [-Waggressive-loop-optimizations]
   for (int pin = A5; pin++;)
                      ~~~^~
C:\Users\bugge\AppData\Local\Temp\.arduinoIDE-unsaved2025420-6596-fhro1s.e7a9r\sketch_may20a\sketch_may20a.ino:6:25: note: within this loop
   for (int pin = A5; pin++;)
                         ^~

And the code:

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("Start");
  for (int pin = A5; pin++;)
  {
    Serial.println(pin);
    delay(500);
  }
}

void loop()
{
  // put your main code here, to run repeatedly:
}

Hi xfpd

That is another part of the same project - this Box controls those Sounds.
The issue with Max was the Editor does not recognise NoteOff, but a Complied EXE does.
So different things happen in the Editor and the EXE.

But this is strictly an Arduino issue!

However, I really want to run the sounds using PD on a Pi-5, but PD's sound handling is awful - no crackles in Max, nothing but crackles in PD...

Hi sterretje

Thanks for the tip, but if the IDE wont see the board - its a MICRO btw - how can I upload a sketch?

Do I need to use an Array if I'm just using One Button and One Trigger?
Can I just reference them directly?

How would I do that?

Many Thanks!

if it is a pro micro have a look at How to Revive a "Bricked" Pro Micro

1 Like

Hi UKHeliBob

Do you mean the BOOM BUTTON Pin 1?
That has worked fine from day 1.

Or do you mean the TRIGGER Pin A5?
The trigger is the one causing problems.

Thanks for the tips!

Upload the blink sketch.
When the IDE reports the memory usage, double tap the reset button. The L-LED should fade in and out for approximately 8 seconds during which the upload can actually be done.

Yes, because on an Arduino Micro it is not used for serial communication with the PC and hence it's safe to use it. UKHeliBob's reply was because you did not mention (in the opening post) which board you used.

1 Like

I thought that what I wrote was quite clear

Hi sterretje

Thanks for the help!

I have switched the IDE to Verbose Output, double-tapped the Boot Button, and (according to the report) I managed to upload your sketch.
However the board was still not recognized as a port (NO PORTS DISCOVERED), until I repeated the process with a full sketch.

The output of the Console Report is below

FQBN: arduino:avr:micro
Using board 'micro' from platform in folder: C:\Users\willh\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6
Using core 'arduino' from platform in folder: C:\Users\willh\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6

Detecting libraries used...
C:\Users\willh\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_MICRO -DARDUINO_ARCH_AVR -DUSB_VID=0x2341 -DUSB_PID=0x8037 -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Micro" -IC:\Users\willh\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino -IC:\Users\willh\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\variants\micro C:\Users\willh\AppData\Local\arduino\sketches\6DF83BFED9E7D272E8326B301B1F270F\sketch\VANILLA_TEST.ino.cpp -o nul
Generating function prototypes...
C:\Users\willh\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_MICRO -DARDUINO_ARCH_AVR -DUSB_VID=0x2341 -DUSB_PID=0x8037 -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Micro" -IC:\Users\willh\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino -IC:\Users\willh\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\variants\micro C:\Users\willh\AppData\Local\arduino\sketches\6DF83BFED9E7D272E8326B301B1F270F\sketch\VANILLA_TEST.ino.cpp -o C:\Users\willh\AppData\Local\Temp\3698187961\sketch_merged.cpp
C:\Users\willh\AppData\Local\Arduino15\packages\builtin\tools\ctags\5.8-arduino11/ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives C:\Users\willh\AppData\Local\Temp\3698187961\sketch_merged.cpp

Compiling sketch...
"C:\\Users\\willh\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_MICRO -DARDUINO_ARCH_AVR -DUSB_VID=0x2341 -DUSB_PID=0x8037 "-DUSB_MANUFACTURER=\"Unknown\"" "-DUSB_PRODUCT=\"Arduino Micro\"" "-IC:\\Users\\willh\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.6\\cores\\arduino" "-IC:\\Users\\willh\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.6\\variants\\micro" "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F\\sketch\\VANILLA_TEST.ino.cpp" -o "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F\\sketch\\VANILLA_TEST.ino.cpp.o"
C:\Users\willh\Documents\Arduino\VANILLA_TEST\VANILLA_TEST.ino: In function 'setup':
C:\Users\willh\Documents\Arduino\VANILLA_TEST\VANILLA_TEST.ino:6:25: warning: iteration 32744 invokes undefined behavior [-Waggressive-loop-optimizations]
   for (int pin = A5; pin++;)
                      ~~~^~
C:\Users\willh\Documents\Arduino\VANILLA_TEST\VANILLA_TEST.ino:6:25: note: within this loop
   for (int pin = A5; pin++;)
                         ^~
Compiling libraries...
Compiling core...
Using precompiled core: C:\Users\willh\AppData\Local\arduino\cores\arduino_avr_micro_edc3bad1bdf47c1d0614a86019fb3ad9\core.a
Linking everything together...
"C:\\Users\\willh\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-gcc" -Wall -Wextra -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega32u4 -o "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.elf" "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F\\sketch\\VANILLA_TEST.ino.cpp.o" "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F/..\\..\\cores\\arduino_avr_micro_edc3bad1bdf47c1d0614a86019fb3ad9\\core.a" "-LC:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F" -lm
"C:\\Users\\willh\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.elf" "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.eep"
"C:\\Users\\willh\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -R .eeprom "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.elf" "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.hex"
"C:\\Users\\willh\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\\Users\\willh\\AppData\\Local\\arduino\\sketches\\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.elf"
Sketch uses 3778 bytes (13%) of program storage space. Maximum is 28672 bytes.
Global variables use 157 bytes (6%) of dynamic memory, leaving 2403 bytes for local variables. Maximum is 2560 bytes.
Waiting for upload port...
Upload port found on COM4

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2"C:\Users\willh\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude" "-CC:\Users\willh\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf" -v  -patmega32u4 -cavr109 "-PCOM4" -b57600 -D "-Uflash:w:C:\Users\willh\AppData\Local\arduino\sketches\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.hex:i"
005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\willh\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM4
         Using Programmer              : avr109
         Overriding Baud Rate          : 57600
         AVR Part                      : ATmega32U4
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  9000  9000 0x00 0x00
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : butterfly
         Description     : Atmel AppNote AVR109 Boot Loader

Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
    Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
    Device code: 0x44

avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading input file "C:\Users\willh\AppData\Local\arduino\sketches\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.hex"
avrdude: writing flash (3778 bytes):

Writing | ################################################## | 100% 0.29s

avrdude: 3778 bytes of flash written
avrdude: verifying flash memory against C:\Users\willh\AppData\Local\arduino\sketches\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.hex:
avrdude: load data flash data from input file C:\Users\willh\AppData\Local\arduino\sketches\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.hex:
avrdude: input file C:\Users\willh\AppData\Local\arduino\sketches\6DF83BFED9E7D272E8326B301B1F270F/VANILLA_TEST.ino.hex contains 3778 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.03s

avrdude: verifying ...
avrdude: 3778 bytes of flash verified

avrdude done.  Thank you.

The sketch reported it uploaded ok, but the board was still undiscoverable, so I repeated the procedure using a full sketch - it uploaded and when I rebooted it - it works!!
Thank you sterretje! Now I can try and make the other board work too!

So - I still have the issue of WHY or HOW the code disabled the board (or the port, or the USB, or the...).

If anyone has an idea WHY the code disabled the board I would be eternally grateful!

I suppose I just could try random changes to see what happens...

:zany_face:

Post #5

Part of the code that you upload contains functionality for board identification by the PC and to react on the software reset (open/close port at 1200 baud) that is issued by the IDE to invoke the bootloader on the board.

Due to a bug in your sketch you can overwrite variables used by the above two functionalities. Sometimes the board is still recognised but will not react on the software reset, other times the board identification is affected.

my guess, yes you really need to fix the bad for loop, but I'm thinking it's your use of MIDIUSB.h that changes the usb device descriptor so it will be detected as a midi device, hence you'll have to do the double tap to reload script..
The Zero has 2 usb ports, native and programming, can program and debug through one while using the native for midi..

I could be wrong, check your device manager before and after plugging in, what does it show as??

good luck.. ~q

i see code running using a println() with following changes

#ifdef MyHW
const int TriggerPin[1] = {A5}; // KICK TRIGGER
#else
const int TriggerPin[1] = {'A5'}; // KICK TRIGGER
#endif
#ifdef MyHW
char pinAssignments[1] = {A5};
#else
char pinAssignments[1] = {'A5'};
#endif

isn't this an infinite loop?

#ifdef MyHW
  for (int pin=A5; pin < 16; pin++) // pin < 16; pin++)
#else
  for (int pin=A5; pin++;) // pin < 16; pin++)
#endif

and more conventionally formatted

//
//  Copyright Will Hitchings 2024
//
//     PLUS-4
//     ======
//
//  Sketch for a Midi Box to control a
//
//        SELF-CONTAINED KICK + SUB SYSTEM
//        ================================
//
//   1x BUTTON SWITCH (D1)
//   1x TRIGGER INPUT  (A5)
//   5x POTENTIOMETERS (A0-1-2-3-4)
//
//    PIN ASSIGNMENTS
//
//    A0 = POT 1 FREQ           CC01
//    A1 = POT 2 KICK 1         CC02
//    A2 = POT 3 KICK 2         CC03
//    A3 = POT 4 KICK 3         CC04
//    A4 = POT 5 KICK SUB    CC05
//    A5 = TRIGGER INPUT    NOTE 36
//    D1 = BUTTON                NOTE 30
//
//    MIDI CHANNEL 1
//
//   = = = CHECK 'boards.txt' ! ! !
//

#define MyHW
#ifdef MyHW
typedef struct {
    byte header;   // cable + command
    byte byte1;    // command + channel
    byte byte2;    // note number or other data
    byte byte3;    // velocity or other data or zero.
} midiEventPacket_t;


struct {
    midiEventPacket_t   read     ()    { midiEventPacket_t p = {};
    return p;
    }
    void                flush    ()    { }
    void                sendMIDI (midiEventPacket_t) { }
} MidiUSB;

#else
# include "MIDIUSB.h"
#endif

// BUTTON + TRIGGER to MIDI Notes
#define BTN_NOTE 30 //  BOOM BUTTON
#define TRIG_NOTE 36 //  KICK TRIGGER

#define deviceChannel 0 //   This is the MIDI channel number 0-15
#define buttonDebounceTime 150 //   Debounce time for each button in milliseconds (prevents multiple triggers due to chatter)

const int ButtonPin[1] = {1}; //    BOOM BUTTON
#ifdef MyHW
const int TriggerPin[1] = {A5}; // KICK TRIGGER
#else
const int TriggerPin[1] = {'A5'}; // KICK TRIGGER
#endif

//    TRIGGER

#ifdef MyHW
char pinAssignments[1] = {A5};
#else
char pinAssignments[1] = {'A5'};
#endif

byte TrigNote[1] = {36};
	// MIDI note
int TrigCutOff[1] = {5};
	// Minimum Analog value to cause a drum hit
int MaxPlayTime[1] = {150};
	// Cycles before a 2nd hit is allowed

boolean VelocityFlag  = true;
boolean activeTrig[1] = {0};             // Array of flags of pad currently playing
int PinPlayTime[1] = {0};               // Counter since pad started to play
byte status1;

int pin = A5;
int hitavg = 0;

//    POTENTIOMETERS

const int NPots = 5; //   total number of POTS
const int potPin[NPots] = {A0, A1, A2 , A3, A4}; //   Arduino POT Pins ; Leave nothing in the array if 0 pots {}

int potCState[NPots] = {0}; // Current state of the pot; delete 0 if 0 pots
int potPState[NPots] = {0}; // Previous state of the pot; delete 0 if 0 pots
int potVar = 0; // Difference between the current and previous state of the pot

int midiCState[NPots] = {0}; // Current state of the midi value; delete 0 if 0 pots
int midiPState[NPots] = {0}; // Previous state of the midi value; delete 0 if 0 pots

const int TIMEOUT = 300; //* Amount of time the potentiometer will be read after it exceeds the varThreshold
const int varThreshold = 20; //* Threshold for the potentiometer signal variation
boolean potMoving = true; // If the potentiometer is moving
unsigned long PTime[NPots] = {0}; // Previously stored time; delete 0 if 0 pots
unsigned long timer[NPots] = {0}; // Stores the time that has elapsed since the timer was reset; delete 0 if 0 pots

// MIDI Assignments

// byte midiCh = 1; //* MIDI channel to be used
byte note = 30; //* Lowest note to be used; 30 = BOOM BUTTON, 36 = KICK TRIGGER
byte cc = 1; //* Lowest MIDI CC to be used

// --------------------------------------------------------

bool InternalLED_state = LOW;

bool buttonState[1] = {0};
unsigned long buttonToggleTime[1] = {0};

//-----------------------------------------------------
// START of SETUP

void setup()
{
    Serial.begin(115200);
    //    Serial.println(hitavg);

    for    (int i=0; i<1; i++) {
        pinMode(ButtonPin[1], INPUT);   // For All buttons
        pinMode(TriggerPin[A5], INPUT);   // For All buttons
    }
}


//-----------------------------------------------------
// START of VOID LOOP

void loop()
{
    Serial.println ("loop:");

    #ifdef MyHW
    for (int pin=A5; pin < 16; pin++) // pin < 16; pin++)
    #else
    for (int pin=A5; pin++;) // pin < 16; pin++)
    #endif
    {
        hitavg = analogRead(pinAssignments[pin]);
        //Serial.println(hitavg);
        // read the input pin

        if((hitavg > TrigCutOff[pin])) {
            if((activeTrig[pin] == false)) {
                if(VelocityFlag == true) {
                    hitavg = (hitavg / 4) -1 ;                                                 // Upper range
                }
                else {
                    hitavg = 127;
                }

                //noteOn(144,TrigNote[pin],hitavg); //note on
                noteOn(deviceChannel, TRIG_NOTE, 127); // Channel, Note, Velocity

                PinPlayTime[pin] = 0;
                activeTrig[pin] = true;
            }
            else {
                PinPlayTime[pin] = PinPlayTime[pin] + 1;
            }
        }

        else if((activeTrig[pin] == true)) {
            PinPlayTime[pin] = PinPlayTime[pin] + 1;
            if(PinPlayTime[pin] > MaxPlayTime[pin]) {
                activeTrig[pin] = false;
                //noteOff(144,TrigNote[pin],,0);
                noteOff(deviceChannel, TRIG_NOTE,0);

            }
        }
    }

    // POTS
    potentiometers();

    midiEventPacket_t rx;
    rx = MidiUSB.read(); // Check for Message
    if (rx.header != 0);  // If message Received

    //     CHECK BUTTON

    for (int i=0; i<1; i++){ // ALL BUTTONS
        if (millis() < buttonToggleTime[i] + buttonDebounceTime){ // If it was recently changed
            continue;                                               // Skip this SWITCH. Do next one
        }

        if (buttonState[i] == 0){ // If BUTTON is Not Pressed Already
            if (digitalRead(ButtonPin[i]) == 0){ // Pin is Low, BUTTON is pressed
                buttonState[i] = 1; // Mark as pressed
                buttonToggleTime[i] = millis(); // Update Event Time
                switch(i){  // Pick which Note it is (from BUTTON ID)
                    case 0:
                    noteOff(deviceChannel, BTN_NOTE, 0); // Channel, Note, Velocity
                    break;

                } // End CHECK SWITCHES

            } // End SWITCHES Read

        } // End IF (SWITCH Not Already Pressed)

        else{ // SWITCH Already Pressed (SWITCH State == 1)

            if (digitalRead(ButtonPin[i]) == 1){ // Pin is High, SWITCH is released
                //toggleOnBoardLED(); // FOR DEBUGGING -  CAN BE REMOVED - WH added ;
                buttonState[i] = 0; // Mark as released
                buttonToggleTime[i] = millis(); // Update Event Time

                // MIDI NOTE OFF MESSAGES FOR SWITCHES
                switch(i){  // Pick which Note it is (from button ID)
                    case 0:
                    noteOn(deviceChannel, BTN_NOTE, 127); // Channel, Note, Velocity
                    break;
                } // End SWITCHES
            }// End SWITCHES READ
        } // End ELSE (SWITCH Already Pressed)
    } // End IF SWITCHES
} // END of VOID LOOP


//-----------------------------------------------------
//  POTENTIOMETERS

void potentiometers()
{
    for (int i = 0; i < NPots; i++) { // Loops through all the potentiometers

        potCState[i] = analogRead(potPin[i]); // reads the pins from arduino

        midiCState[i] = map(potCState[i], 0, 1023, 0, 200); // Maps the reading of the potCState to a value usable in midi

        potVar = abs(potCState[i] - potPState[i]); // Calculates the absolute value between the difference between the current and previous state of the pot

        if (potVar > varThreshold) { // Opens the gate if the potentiometer variation is greater than the threshold
            PTime[i] = millis(); // Stores the previous time
        }

        timer[i] = millis() - PTime[i]; // Resets the timer 11000 - 11000 = 0ms

        if (timer[i] < TIMEOUT) { // If the timer is less than the maximum allowed time it means that the potentiometer is still moving
            potMoving = true;
        }
        else {
            potMoving = false;
        }

        if (potMoving == true) { // If the potentiometer is still moving, send the change control
            if (midiPState[i] != midiCState[i]) {

                // Sends  MIDI CC
                // Use if using with ATmega32U4 (micro, pro micro, leonardo...)
                controlChange(deviceChannel, cc + i, midiCState[i]); //  (channel, CC number,  CC value)
                MidiUSB.flush();

                potPState[i] = potCState[i]; // Stores the current reading of the potentiometer to compare with the next
                midiPState[i] = midiCState[i];
            }
        }
    }
}


void controlChange (
uint8_t channel,
uint8_t control,
uint8_t value )
{
    midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
    MidiUSB.sendMIDI(event);
}


void noteOn(byte channel, byte pitch, byte velocity) {
    midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOn);
    MidiUSB.flush();// Send note now
}


void noteOff(byte channel, byte pitch, byte velocity) {
    midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOff);
    MidiUSB.flush(); // Send note now
}

See post #3. The chance that code alone can permanently disable a board is essentially zero.

If you want help solving the REAL problem, post a complete wiring diagram (pencil and paper is preferred), with pins, connections and parts clearly labeled, links to all the components, and the details of the power supply.

Also, clearly describe what you were doing when the board failed, and what you did in attempts to revive it.

Hi jremington

Sorry, that seems as if you mis-read my initial post, about how it worked fine - WITHOUT the trigger part. Simply adding that extra code -disabled- the board.

I don't think I said KILLED, as per the Topic - also I have managed to get the disabled boards working again, but using an earlier sketch - without the Trigger code.

It really is only the Trigger code disabling the boards, as I said before, it works fine up until I add that code in.

As a (I repeat) NON-Programmer (sorry again) it is really hard trying to understand the problem, so people replying with coding answers I don't understand makes things even more confusing...

I wish maths and code logic made sense to me - but it doesn't (blame my brain), so I have to try and do what I can how I can, which means I have to ask questions which sound really stupid, and post code which doesn't make sense to 'proper' programmers.

Again I can only apologize.