Using Photon RGB-led pins (aka 27-29?) for PWM

Hello Particle community!

I’ve been poring over the documentation but can’t seem to find an answer…

I’m trying to use pins 27, 28, 29 on the underside of the Photon for PWM (assuming that’s what @ScruffR meant here), which made sense after checking the underside layout image and referencing here (since it’s a completely separate PWM TIMer for the onboard RGB):

After (very carefully) soldering the tags, @BDub’s example worked with separate LEDs (it appears the RGB-wiring pinout is for common-anode).

I’d like to know how I can reference these pins without using the RGB.colour methods - is this possible? I’ve tried many different combinations (MICRO_GPIO_# / PA# / Photon & pin #) but I can’t seem to find the answer…

…this is ASSUMING @ScruffR was talking about these and not the BTCX pins on top (WAY too tiny for me)!

PS: AWESOME community guys, I’m spreading the word about Particle to random strangers everywhere! :wink:

I have not yet tried it myself but looking at the open source pinmap_hal.h I found this

// DAC pins on Photon
#define DAC1 16
#define DAC2 13

// RGB LED pins
#define RGBR 21
#define RGBG 22
#define RGBB 23

So try RGBR, RGBG and RGBB but make sure to take control over RGB.
I’ve no idea why these pin numbers don’t line up with the docs :confused:

and the respective implementation file pinmap_hal.c


/* COMMON TO PHOTON, P1 and ELECTRON */
/* D0            - 00 */ { GPIOB, GPIO_Pin_7, GPIO_PinSource7, NONE, NONE, TIM4, TIM_Channel_2, PIN_MODE_NONE, 0, 0 },
/* D1            - 01 */ { GPIOB, GPIO_Pin_6, GPIO_PinSource6, NONE, NONE, TIM4, TIM_Channel_1, PIN_MODE_NONE, 0, 0 },
/* D2            - 02 */ { GPIOB, GPIO_Pin_5, GPIO_PinSource5, NONE, NONE, TIM3, TIM_Channel_2, PIN_MODE_NONE, 0, 0 },
/* D3            - 03 */ { GPIOB, GPIO_Pin_4, GPIO_PinSource4, NONE, NONE, TIM3, TIM_Channel_1, PIN_MODE_NONE, 0, 0 },
/* D4            - 04 */ { GPIOB, GPIO_Pin_3, GPIO_PinSource3, NONE, NONE, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* D5            - 05 */ { GPIOA, GPIO_Pin_15, GPIO_PinSource15, NONE, NONE, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* D6            - 06 */ { GPIOA, GPIO_Pin_14, GPIO_PinSource14, NONE, NONE, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* D7            - 07 */ { GPIOA, GPIO_Pin_13, GPIO_PinSource13, NONE, NONE, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* NOT USED      - 08 */ { NULL, NONE, NONE, NONE, NONE, NULL, NONE, NONE, NONE, NONE },
/* NOT USED      - 09 */ { NULL, NONE, NONE, NONE, NONE, NULL, NONE, NONE, NONE, NONE },
/* A0            - 10 */ { GPIOC, GPIO_Pin_5, GPIO_PinSource5, ADC_Channel_15, NONE, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* A1            - 11 */ { GPIOC, GPIO_Pin_3, GPIO_PinSource3, ADC_Channel_13, NONE, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* A2            - 12 */ { GPIOC, GPIO_Pin_2, GPIO_PinSource2, ADC_Channel_12, NONE, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* DAC2, A3      - 13 */ { GPIOA, GPIO_Pin_5, GPIO_PinSource5, ADC_Channel_5, DAC_Channel_2, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* A4            - 14 */ { GPIOA, GPIO_Pin_6, GPIO_PinSource6, ADC_Channel_6, NONE, TIM3, TIM_Channel_1, PIN_MODE_NONE, 0, 0 },
/* A5            - 15 */ { GPIOA, GPIO_Pin_7, GPIO_PinSource7, ADC_Channel_7, NONE, TIM3, TIM_Channel_2, PIN_MODE_NONE, 0, 0 },
/* DAC, DAC1, A6 - 16 */ { GPIOA, GPIO_Pin_4, GPIO_PinSource4, ADC_Channel_4, DAC_Channel_1, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* WKP, A7       - 17 */ { GPIOA, GPIO_Pin_0, GPIO_PinSource0, ADC_Channel_0, NONE, TIM5, TIM_Channel_1, PIN_MODE_NONE, 0, 0 },
/* RX            - 18 */ { GPIOA, GPIO_Pin_10, GPIO_PinSource10, NONE, NONE, TIM1, TIM_Channel_3, PIN_MODE_NONE, 0, 0 },
/* TX            - 19 */ { GPIOA, GPIO_Pin_9, GPIO_PinSource9, NONE, NONE, TIM1, TIM_Channel_2, PIN_MODE_NONE, 0, 0 },
/* SETUP BUTTON  - 20 */ { GPIOC, GPIO_Pin_7, GPIO_PinSource7, NONE, NONE, NULL, NONE, PIN_MODE_NONE, 0, 0 },
/* RGBR          - 21 */ { GPIOA, GPIO_Pin_1, GPIO_PinSource1, NONE, NONE, TIM2, TIM_Channel_2, PIN_MODE_NONE, 0, 0 },
/* RGBG          - 22 */ { GPIOA, GPIO_Pin_2, GPIO_PinSource2, NONE, NONE, TIM2, TIM_Channel_3, PIN_MODE_NONE, 0, 0 },
/* RGBB          - 23 */ { GPIOA, GPIO_Pin_3, GPIO_PinSource3, NONE, NONE, TIM2, TIM_Channel_4, PIN_MODE_NONE, 0, 0 }

I’d have to look at the implementation of analogWrite() if the sanity checks prevent you from using these pins that way or not.


Update:
The reason for the difference in numbers is that the phyiscal pins/pads on the Photon are numbered sequentially to their physical location (with the BT coexistence pins included), but the GPIO numbers are not taking these into account as they are not meant for direct access.

@woopsie, have you had any luck getting these pins to work as GPIO?

@ScruffR, I tried a simple sketch below to try controlling the pins but, the Red led does not go on during the loop

void setup() {
    RGB.control(true);
    RGB.color(0, 0, 0);
    pinMode(RGBR, OUTPUT);
}

void loop() {
    digitalWrite(RGBR, HIGH);
}

@wesner0019, I just tested using an RGB LED (27=R, 28=G, 29=B) defined as 21-23 (respectively), and they all work using digitalWrite and analogWrite (including PWM).

In my test I used the RGB method to take / release control (only) and did everything within Setup so my status-LED was unaffected afterwards; try removing the RGB.color(0, 0, 0) or check your soldering, it’s a very tiny pad!

Some observations:

  • The onboard status-LED changes according to the Setup test program, but uses different colors (R=>blue, G=>purple, B=>yellow) regardless of digital/analogWrite.
  • For analogWrite within Setup, even though I use RGB.color(false) at the end of Setup to release control, the external LED still acts as the sole status-LED for the Photon by breathing blue.
  • While the external RGB is acting as status (after using analogWrite in Setup), the onboard LED shows white (just like the first millisecond on startup).

PS: @ScruffR, thank you very much for your quick reply & helpful information - legend!

1 Like

@wesner0019 & @woopsie, have a play with this (lazy) sketch

void setup(void) 
{
    RGB.control(true);
    pinMode(RGBR, OUTPUT);
    pinMode(RGBG, OUTPUT);
    pinMode(RGBB, OUTPUT);
    Particle.function("RED", setRed);
    Particle.function("BLUE", setBlue);
    Particle.function("GREEN", setGreen);
}
void loop() 
{
}
int setRed(String val)
{
    analogWrite(RGBR, 255-val.toInt());
    return val.toInt();
}
int setGreen(String val)
{
    analogWrite(RGBG, 255-val.toInt());
    return val.toInt();
}
int setBlue(String val)
{
    analogWrite(RGBB, 255-val.toInt());
    return val.toInt();
}

The point why you see other colors than expected is that the RGB LED is common anode. So you have to invert the logic. Pin HIGH means both sides of the diode are same level, so no current flows. Pin LOW means the common anode 3.3V can drive the current to flow through the diode down to GND.

LOL yeah totally missed that!.