Pin to Green LED always on

This is my first post on the forum, so I apologize if I make any mistakes. I'm also very new to making things like this, so forgive me if I use the wrong terminology.

My Goal: I am trying to make a program that turns the LED on and off after a button press.

The Problem: The pin attached to the green LED always outputs HIGH. It doesn't matter if I switch to a different pin or swap the order of the LEDs, but as long as I have pinMode(GREEN, OUTPUT) enabled in my code, the output of that corresponding pin will always be HIGH.

Schematic

Photo


(In case my schematic wasn't drawn correctly)

Specs: I am using a common anode 3W RGB led and an ItsyBitsy M0 Express, based on SAMD21. The push button is a push button.

Code

#include <SPI.h>
#include <Arduino.h> 
#include <stdlib.h>

#define BUTTON 13

#define RED 12
#define GREEN 10
#define BLUE 11

// Timer Interrupt
#define CPU_HZ 48000000
#define TIMER_PRESCALER_DIV 1024

void setColor(int red, int green, int blue) {
  analogWrite(RED, 255-red);
  analogWrite(GREEN, 255-green);
  analogWrite(BLUE, 255-blue);
}

void led_off(){
  setColor(0, 0, 0);
}

void led_on(){
  setColor(255, 255, 255);
}

#define MAX_LIGHT_STATES 1
volatile int cur_light_state;

void change_light_state(void) {
  cur_light_state = (cur_light_state == MAX_LIGHT_STATES) ? 0 : (cur_light_state + 1);
}

void TC3_Handler(void){
  switch(cur_light_state){
    case 0:
      Serial.println("OFF");
      led_off(); // Off statae
      break;
    case 1:
      Serial.println("ON");
      led_on(); // Solid color on
      break;
  }

  TC3->COUNT16.INTFLAG.bit.MC0 = 1;
}

void setup() {
  Serial.begin(9600);

  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  setColor(0,0,0);

  // set up button
  pinMode(BUTTON, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(BUTTON), change_light_state, FALLING); 

  // Configure asynchronous clock source
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_TCC2_TC3_Val;    // select TC3 peripheral channel
  GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_GEN_GCLK0;        // select source GCLK_GEN[0]
  GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN;         // enable generic clock
  while(GCLK->STATUS.bit.SYNCBUSY){}; // status syncbusy set when write starts

  // Synchronous bus clock is enabled by default

  TC3->COUNT16.CTRLA.bit.ENABLE = 0; // disable clock to write to it
  while(TC3->COUNT16.STATUS.bit.SYNCBUSY);

  Serial.println("Clock disabled");

  // Configure Count Mode (16-bit)
  TC3->COUNT16.CTRLA.bit.MODE = 0x0; 

  // Configure Compare Mode for TC
  TC3->COUNT16.CTRLA.bit.WAVEGEN = 0x1; // 0x1 is Match Frequency mode

  // Configure prescaler for DIV32
  TC3->COUNT16.CTRLA.bit.PRESCALER = 0x6;

  // Initialize compare value for 100mS @ 500kHz
  TC3->COUNT16.CC[0].reg = 50000;
  while(TC3->COUNT16.STATUS.bit.SYNCBUSY );

  // Enable TC3 compare mode interrupt generation
  TC3->COUNT16.INTENSET.bit.MC0 = 0x1;    // Enable match interrupts on compare channel 0 

  // Enable TC3
  TC3->COUNT16.CTRLA.bit.ENABLE = 1;
  while(TC3->COUNT16.STATUS.bit.SYNCBUSY);

  Serial.println("TC3 enabled");

  NVIC_SetPriority(TC3_IRQn, 3); // 4 priority levels 0-3, higher number is higher priority
  NVIC_EnableIRQ(TC3_IRQn);
}

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

To explain my code in more detail, I am using the timer counter to update whether my LED is on or off based on the variable "cur_light_state" at ~250 ms intervals. The tracker variable changes based on an interrupt generated from a button press.

When the board is on, I've noticed that the LED flashes at the rate I've set the timer counter to. I have a suspicion that the two are linked somehow, though I can't see a reason why it would "follow" the green LED.

Note that I've also tried switching TC3 out for TC4 with the same results.

I am aware there are better, more simple ways to code this with the same functionality, but that is neither here nor there. This is a simplified test version of my original code for debugging purposes, there is a reason to my madness. The only problem I seek answer for is why the green LED is always on. Thank you for reading this far, by the way.

Where are the resistors? How much does each LED draw, and how much can a pin source?

There are no resistors, each LED draws ~350mA, and all logic pins give 3.3 V.

Ok, fair enough, I didn't specify that current is what I'm getting at.

I'm not sure where to find information on how much current a pin can source. It only mentions the voltage each pin can provide on the original listing on Adafruit.

Can I ask what you're trying to figure out with this information?

I'm not trying to figure out anything. I'm trying to steer you into understand that you're totally overloading your pins, and that they probably are destroyed already.

Actually neither do I. I find it weird that Adafruit would miss such a crucial detail.

Edit: Arduinos M0 board description says
DC Current per I/O Pins 7 mA

I'm surprised that the green LED still can be lit.

Adafruit may have made it hard to find, but Microchip didn't. From the SAMD21 datasheet (which is the processor on the Itsy Bitsy M0):

Oh, and from the Absolute Maximum section:

Maximum source current is 46mA and maximum sink current is 65mA per cluster. A cluster is a group of GPIOs as shown in the table below.

I found it too, after I read from Arduinos M0 page. Deeeeeeeeep down the datasheet :face_with_raised_eyebrow:

Hold on. What do you mean by overloading and destroyed? Is it that the pins don't work anymore? Sorry, I'm not too well-versed on this topic.

I cheated and used the table of contents. :slight_smile:

So did I! Deeeeeeeeep down the datasheet.... pointing even deeper! Microchip just have to be different :upside_down_face:

If a pin source max 7 mA, and something else can sink 350 mA, that's just like a short to the pin. So I'm afraid the pins doesn't work anymore (at least they shouldn't according to all electric laws applicable).

? But my program works as intended when I'm not testing the code I posted specifically. The LED is able to function just fine, and all of that? It's only when I try to test the above code that this problem happens.

You've connected an output to power through a diode with no current limiting.

Output pins have an absolute maximum output current rating, beyond which you've voided the warranty. If the pins aren't dead, they're damaged.

Imagine you have no circuit breakers in your house, and you've shorted an outlet. That's pretty much what you've done.

Can you give a datasheet for that LED?

First priority here isn't the code, but the hardware.

Luckily, there is one this time

Ouch on the forward currents.

Look at the forward voltages. Especially for green and blue.

What voltage does your board run at again?

3.3 ... I think I see the problem now, yeah.

In hindsight, what steps should I have taken to prevent this from happening? Adding resistors or using a board that can supply more than what the LED requires?

And it's very late here (or very early), which is my only excuse for not noticing the glaring hardware error right from the start.

Solder those headers. It WILL NOT WORK until you do. The LEDs still won't work, but nothing will work without an electrical connection.

It might just have saved your I/O pins though.