I just ordered a PCB for my project when I noticed that PD5 wasn't a standard I/O pin programmed into the Arduino Leanardo bootloader. I plan on using PD5 as a signal input to let the uC know when the micro USB cable is plugged into the board. Since the PCB's are on their way here, it's too late to make this change to my board. I've read some forms, and it may be possible to use PD5 as a input pin, but I don't know the specific details on how to do that. Would anybody be able to help me out?
ClarinetJay:
I noticed that PD5 wasn't a standard I/O pin programmed into the Arduino Leanardo bootloader.
The first thing that you need to understand is that the bootloader has absolutely nothing to do with programming standard I/O pins. The only thing the bootloader does is to facilitate uploading sketches to the board.
The pins are programmed by the variant file of the boards platform, which is part of your sketch, not part of the bootloader:
PD5 is Arduino pin 30 and you can use it with digitalRead(), digitalWrite(), and all the other Arduino functions just like any other Arduino pin.
pert:
PD5 is Arduino pin 30 and you can use it with digitalRead(), digitalWrite(), and all the other Arduino functions just like any other Arduino pin.
For the ATMega32U4, I thought PD5 was pin 22 on the uC. But in any case, all I have to do in the setup function is include: pinMode(PD5, INPUT).
Please excuse my lack of knowledge with the Atmel uC. Programming isn't my specialty.
ClarinetJay:
For the ATMega32U4, I thought PD5 was pin 22 on the uC.
I'll take your word for it because I don't feel like looking at the datasheet. However, physical pin numbers are only of relevance when designing a circuit board. This is a common misconception for those using bare chips with Arduino for the first time. There is no relation between physical pin numbers and Arduino pin numbers (or if there is, it's purely coincidental). Arduino pin numbers are just arbitrary identifiers assigned to IO pins to allow them to be easily referenced in the code. If you think about it, it wouldn't make sense anyway because you'd end up with gaps in your pin numbers for the physical pin numbers of the non-IO pins like the power bus and crystal.
ClarinetJay:
in any case, all I have to do in the setup function is include: pinMode(PD5, INPUT).
Another common misconception. Arduino pin numbers are completely different from the port/bit notation used for low level programming. You are welcome to use the register level port bit addressing in your Arduino sketch if you like, but you can not do this with the standard Arduino API functions like pinMode(), digitalRead(), digitalWrite(), etc. These can only be used with Arduino pin numbers. PD5 is actually just a convenience macro defined as 5 (for bit number 5). So your code pinMode(PD5, INPUT) is setting Arduino pin 5. Arduino pin five happens to be mapped to PC6.
If you look at the code at the link I posted above, you can see all the pin mappings for the Leonardo (and other ATmega32U4-based Arduino boards). The Arduino pin number is the index of the arrays that map the port and bit addresses of the IO pins. Here's the one that does the port mapping:
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, // D0 - PD2
PD, // D1 - PD3
PD, // D2 - PD1
PD, // D3 - PD0
PD, // D4 - PD4
PC, // D5 - PC6
PD, // D6 - PD7
PE, // D7 - PE6
PB, // D8 - PB4
PB, // D9 - PB5
PB, // D10 - PB6
PB, // D11 - PB7
PD, // D12 - PD6
PC, // D13 - PC7
PB, // D14 - MISO - PB3
PB, // D15 - SCK - PB1
PB, // D16 - MOSI - PB2
PB, // D17 - SS - PB0
PF, // D18 - A0 - PF7
PF, // D19 - A1 - PF6
PF, // D20 - A2 - PF5
PF, // D21 - A3 - PF4
PF, // D22 - A4 - PF1
PF, // D23 - A5 - PF0
PD, // D24 / D4 - A6 - PD4
PD, // D25 / D6 - A7 - PD7
PB, // D26 / D8 - A8 - PB4
PB, // D27 / D9 - A9 - PB5
PB, // D28 / D10 - A10 - PB6
PD, // D29 / D12 - A11 - PD6
PD, // D30 / TX Led - PD5
};
You can see that element 30 of the list is mapped to port D.
Now here's the array that maps the port bits to the Arduino pin numbers:
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
_BV(2), // D0 - PD2
_BV(3), // D1 - PD3
_BV(1), // D2 - PD1
_BV(0), // D3 - PD0
_BV(4), // D4 - PD4
_BV(6), // D5 - PC6
_BV(7), // D6 - PD7
_BV(6), // D7 - PE6
_BV(4), // D8 - PB4
_BV(5), // D9 - PB5
_BV(6), // D10 - PB6
_BV(7), // D11 - PB7
_BV(6), // D12 - PD6
_BV(7), // D13 - PC7
_BV(3), // D14 - MISO - PB3
_BV(1), // D15 - SCK - PB1
_BV(2), // D16 - MOSI - PB2
_BV(0), // D17 - SS - PB0
_BV(7), // D18 - A0 - PF7
_BV(6), // D19 - A1 - PF6
_BV(5), // D20 - A2 - PF5
_BV(4), // D21 - A3 - PF4
_BV(1), // D22 - A4 - PF1
_BV(0), // D23 - A5 - PF0
_BV(4), // D24 / D4 - A6 - PD4
_BV(7), // D25 / D6 - A7 - PD7
_BV(4), // D26 / D8 - A8 - PB4
_BV(5), // D27 / D9 - A9 - PB5
_BV(6), // D28 / D10 - A10 - PB6
_BV(6), // D29 / D12 - A11 - PD6
_BV(5), // D30 / TX Led - PD5
};
You can see that element 30 of the array is mapped to bit 5. So put them together and you get the definition of Arduino pin 30 as PD5.
Some thing that maybe is confusing while we're talking about port D is that you'll sometimes see the digital Arduino pin numbers prefixed with "D", but that just stands for "digital", not for port D.
None of this is something we would ever want to expose a beginner to. A beginner only needs to know that they use the numbers printed on their Arduino board in the Arduino functions and everything just works. They might not end up opening up the hood and looking at the variant files for years, if ever. You're coming in to this from a different direction than normal because you're making a custom PCB before you've learned how the Arduino framework works. Most users do that in the opposite order..
I've just started to get my feet wet with ProMicros. And after a day fiddling I have decided to not touch the two LED pins in code. It might have been my code, but when I tried to use the RX led, I had to use "double reset" to activate the boot loader if I wanted to upload code. Still need to do a bit more investigation before posting a question about it.
Anyway, why do you need to detect if the USB is connected?
I use LED_BUILTIN_RX all the time as an output. The reason is that the Pro Micro doesn't have a dedicated on board LED so I appropriate LED_BUILTIN_RX as a replacement for LED_BUILTIN. I've never had a problem. I've never had any need to use it as an input though.
Were you using it as an output when you had the problem @sterretje?
Yes, output as a replacement for LED_BUILTIN. But I need to reproduce and investigate a little further before others start wasting time on it
Note that I'm brand-spanking new to the ProMicro (not so much the 32U4) so I might have made mistakes.
sterretje:
I've just started to get my feet wet with ProMicros. And after a day fiddling I have decided to not touch the two LED pins in code. It might have been my code, but when I tried to use the RX led, I had to use "double reset" to activate the boot loader if I wanted to upload code. Still need to do a bit more investigation before posting a question about it.Anyway, why do you need to detect if the USB is connected?
I'm working on a project revolving around Adafruit's Sound Board. Basically because of the way my PCB is designed, I need to reset the volume level (as a function of the C program) when the Micro USB Cable is removed.
If your code makes use of serial prints, you can make use of something based on below
// if the output buffer is full
if(Serial.availableForWrite() == 0)
{
// reset sound board
}
That is, if Pert's replies don't help you.