ATMEGA32U4: Difference between revisions

From Nottinghack Wiki
Jump to navigation Jump to search
d
 
(31 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{project|status=In Progress|primary=[[User:Msemtd|Michael Erskine]]|type=member|}}
Many hackers wish to produce a USB device that presents itself as a HID joypad, keyboard, or mouse to a PC or Pi to provide interesting interactions and I/O opportunities in a "standardised" manner. The Arduino Micro and more recently the Leonardo use a micro with an inbuilt USB peripheral device that can be repurposed directly. Previously the Arduino boards used a second small micro or dedicated USB chip (essentially another micro) to perform the USB-serial task but the cost of this additional device was high (often more than the micro itself) and that essential USB device feature soon found itself integrated into a number of Atmel chips. This was an opportunity for the Arduino project to divorce itself from a massive dependence on FTDI (in good time for [https://www.google.co.uk/search?q=%23FTDIGATE #FTDIGATE] !!) and for hackers to get involved with the delights of the at90usb82, atmega16u2, etc. as secondary processors for USB comms.
Many hackers wish to produce a USB device that presents itself as a HID joypad, keyboard, or mouse to a PC or Pi to provide interesting interactions and I/O opportunities in a "standardised" manner. The Arduino Micro and more recently the Leonardo use a micro with an inbuilt USB peripheral device that can be repurposed directly. Previously the Arduino boards used a second small micro or dedicated USB chip (essentially another micro) to perform the USB-serial task but the cost of this additional device was high (often more than the micro itself) and that essential USB device feature soon found itself integrated into a number of Atmel chips. This was an opportunity for the Arduino project to divorce itself from a massive dependence on FTDI (in good time for [https://www.google.co.uk/search?q=%23FTDIGATE #FTDIGATE] !!) and for hackers to get involved with the delights of the at90usb82, atmega16u2, etc. as secondary processors for USB comms.


Time rolls on and the excitement of the brilliant but non-open Minimus project dies down to find a number of crazy-cheap options where the USB chip is the main chip. The Atmega32U4 can be found on the Arduino Micro (currently for about £20) but also on the wonderful [http://www.pjrc.com/teensy/index.html Teensy 2.0] and some really cheap little boards from China that at £4 each are cheaper than buying just the chip from here in the UK (in reasonable quantities). Myself (Michael E) and Spencer have ordered some of these bonkers-cheap units for initial testing and evaluation.
Time rolls on and the excitement of the brilliant but non-open Minimus project dies down to find a number of crazy-cheap options where the USB chip is the main chip. The Atmega32U4 can be found on the Arduino Micro (currently for about £20) but also on the wonderful [http://www.pjrc.com/teensy/index.html Teensy 2.0] and some really cheap little "Pro Micro" boards from China that at £4 each are cheaper than buying just the chip from here in the UK (in reasonable quantities). Myself (Michael E) and Spencer have ordered some of these bonkers-cheap units for initial testing and evaluation. They would appear to be clones of the Sparkfun Pro Micro https://www.sparkfun.com/products/12640


== Info Dump ==
== Info Dump ==
* http://www.atmel.com/devices/atmega32u4.aspx
* http://www.atmel.com/devices/atmega32u4.aspx
* full datasheet: http://www.atmel.com/Images/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf
* full datasheet: http://www.atmel.com/Images/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf
* short summary: http://www.atmel.com/Images/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Summary.pdf
* short summary: http://www.atmel.com/Images/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Summary.pdf


* 10x board for £40: http://www.ebay.co.uk/itm/10x-Arduino-Pro-Micro-Leonardo-compatible-ATMEGA-32U4-5v-NEW-TESTED-UK-Stock-/161766720163?ssPageName=ADME:L:OU:GB:3160
* DELIVERY 1:  10x board for £40: http://www.ebay.co.uk/itm/10x-Arduino-Pro-Micro-Leonardo-compatible-ATMEGA-32U4-5v-NEW-TESTED-UK-Stock-/161766720163?ssPageName=ADME:L:OU:GB:3160
* 1x board for £6
* 1x board for £6
* 1x board - possibly even better (see fixes in description - to be compared with our delivery) http://www.ebay.co.uk/itm/Leonardo-Pro-Micro-ATmega32U4-16MHz-5V-Replace-ATmega328-Module-for-Arduino-Nano-/331611815908?hash=item4d359abfe4


== Initial Works ==
== Initial Works for DELIVERY 1 ==


* board inspection: -
* board inspection: -
Line 25: Line 26:
     ATMEL
     ATMEL
     MEGA32U4
     MEGA32U4
    -MU
     1448E    TH
     1448E    TH
     A2N7XA
     A2N7XA
Line 34: Line 36:
* bad oscillator circuitry or configuration
* bad oscillator circuitry or configuration
* pinout mapping for Arduino/teensy/Micro
* pinout mapping for Arduino/teensy/Micro
    J1  |USBu|   
    TX0          RAW
    RX1          GND
    GND          RST
    GND          VCC
      2          A3
      3          A2
      4          A1
      5          A0
      6          15
      7          14
      8          16
      9          10
  +----------------+


== Michael's USB-HID Work ==
== Michael's USB-HID Work ==
Line 40: Line 58:
* Minimus
* Minimus
* LUFA
* LUFA
* Teensy and Teensyduino
* Teensy and Teensyduino - holy grail! Configurable joysticks in Arduino IDE http://www.pjrc.com/teensy/td_joystick.html
* KADE
* KADE
* UnoJoy
* UnoJoy
* https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide
** followed and uploaded the onboard LED driving code - works well!
** now to create additional USB HID capabilities in the board definition
** https://github.com/sparkfun/SF32u4_boards
New project - very similar...
* http://www.instructables.com/id/Turn-an-N64-Controller-into-a-USB-Gamepad-using-an/
Test for ProMicro with 8 inputs and keyboard output: -
<div style ="height:200px;overflow-x:hidden;overflow-y:auto;border: 4px solid green;">
<syntaxhighlight lang="cpp" line="GESHI_FANCY_LINE_NUMBERS">
static uint8_t bprev;
static uint8_t bnew;
const int pmin = 2;
const int pmax = 9;
void setup() {
 
  for(int i = pmin; i <= pmax; i++){
    pinMode(i, INPUT_PULLUP);
  }
  Serial.begin(9600);
  Keyboard.begin();
  bprev = bnew = btn_read();
}
void loop() {
  bnew = btn_read();
  if(bnew != bprev){
    Keyboard.write('z');
    Serial.print("btns = ");
    Serial.println(bnew, HEX);
    bprev = bnew;
  }
  // force change with any serial input
  if(Serial.available() > 0) {
      int b = Serial.read();
      Serial.print("RX: ");
      Serial.println(b, DEC);
      bprev = ~bprev;
  }
}
uint8_t btn_read(void) {
  uint8_t v = 0;
  for(int i = pmin; i <= pmax; i++){
    bitWrite(v, i-pmin, digitalRead(i));
  } 
  return v; 
}
</syntaxhighlight>
</div>
* HID descriptor help http://www.usb.org/developers/hidpage#HID Descriptor Tool
Test for ProMicro with 8 inputs, debounce, multitasking and serial output: -
<div style ="height:200px;overflow-x:hidden;overflow-y:auto;border: 4px solid green;">
<syntaxhighlight lang="cpp" line="GESHI_FANCY_LINE_NUMBERS">
/* Pro Micro Test Code
  by: Nathan Seidle
  modified by: Jim Lindblom
  SparkFun Electronics
  date: September 16, 2013
  license: Public Domain - please use this code however you'd like.
  It's provided as a learning tool.
  This code is provided to show how to control the SparkFun
  ProMicro's TX and RX LEDs within a sketch. It also serves
  to explain the difference between Serial.print() and
  Serial1.print().
  modified by: Michael Erskine
  Nottingham Hackspace
  date: August 28th, 2015
  Added digital inputs from 2-9 with debounce and simple multitasking
 
*/
int RXLED = 17;  // The RX LED has a defined Arduino pin
// The TX LED was not so lucky, we'll need to use pre-defined
// macros (TXLED1, TXLED0) to control that.
// (We could use the same macros for the RX LED too -- RXLED1,
//  and RXLED0.)
void setup()
{
  pinMode(RXLED, OUTPUT);  // Set RX LED as an output
  // TX LED is set as an output behind the scenes
  Serial.begin(9600); //This pipes to the serial monitor
  Serial1.begin(9600); //This is the UART, pipes to sensors attached to board
  inputs_setup();
}
const int da_start = 2;
const int da_num = 4;
static uint8_t da_inputs = 0;
void inputs_setup(void) {
  for(int i = 0; i < da_num; i++) {
    pinMode(da_start + i, INPUT_PULLUP);
  }
  da_inputs = inputs_read();
}
uint8_t inputs_read(void)
{
  uint8_t da_samp = 0;
  for(int i = 0; i < da_num; i++) {
    bitWrite(da_samp, i, (digitalRead(da_start + i) ? 0 : 1));
  }
  return da_samp;
}
void loop()
{
  task_led_toggle();
  task_inputs();
  task_serial_read();
}
void task_inputs(void)
{
  static uint32_t last;
  uint32_t now = millis();
  if(now - last > 5) {
    last = now;
    uint8_t da_samp = inputs_read();
    uint8_t toggle;
    da_samp = debounce(da_samp, &toggle);
    if(da_samp != da_inputs) {
      da_inputs = da_samp;
      Serial.print("Inputs: ");
      Serial.println(da_inputs, BIN);
    }
  }
}
void task_led_toggle(void)
{
  static uint32_t last;
  static bool on = false;
  uint32_t now = millis();
  if(now - last > 1000) {
    last = now;
    // Serial.println("Hello world");  // Print "Hello World" to the Serial Monitor
    // Serial1.println("Hello!");  // Print "Hello!" over hardware UART
    if(on){
      digitalWrite(RXLED, LOW);  // set the LED on
      TXLED0; //TX LED is not tied to a normally controlled pin
    } else {
      digitalWrite(RXLED, HIGH);    // set the LED off
      TXLED1;
    }
    on = !on;
  }
}
void task_serial_read(void) {
  // TODO
}
/*
* http://www.compuphase.com/electronics/debouncing.htm
*/
unsigned char debounce(unsigned char sample, unsigned char *toggle)
{
    static unsigned char state, cnt0, cnt1;
    unsigned char delta;
    delta = sample ^ state;
    cnt1 = (cnt1 ^ cnt0) & delta;
    cnt0 = ~cnt0 & delta;
    *toggle = delta & ~(cnt0 | cnt1);
    state ^= *toggle;
    return state;
}
</syntaxhighlight>
</div>
Test for ProMicro with USB HID joystick, 8 inputs, debounce, multitasking and serial output (NB: needs mods to Arduino core USBAPI.h and HID.cpp in \arduino-1.6.5-r2\hardware\arduino\avr\cores\arduino): -
<div style ="height:200px;overflow-x:hidden;overflow-y:auto;border: 4px solid green;">
<syntaxhighlight lang="cpp" line="GESHI_FANCY_LINE_NUMBERS">
/* Pro Micro Test Code
  by: Nathan Seidle
  modified by: Jim Lindblom
  SparkFun Electronics
  date: September 16, 2013
  license: Public Domain - please use this code however you'd like.
  It's provided as a learning tool.
  This code is provided to show how to control the SparkFun
  ProMicro's TX and RX LEDs within a sketch. It also serves
  to explain the difference between Serial.print() and
  Serial1.print().
  modified by: Michael Erskine
  Nottingham Hackspace
  date: August 28th, 2015
  Added digital inputs from 2-9 with debounce and simple multitasking
 
*/
int RXLED = 17;  // The RX LED has a defined Arduino pin
// The TX LED was not so lucky, we'll need to use pre-defined
// macros (TXLED1, TXLED0) to control that.
// (We could use the same macros for the RX LED too -- RXLED1,
//  and RXLED0.)
// Joystick State
static JoyState_t JoySt;
void setup()
{
  pinMode(RXLED, OUTPUT);  // Set RX LED as an output
  // TX LED is set as an output behind the scenes
  Serial.begin(9600); //This pipes to the serial monitor
  Serial1.begin(9600); //This is the UART, pipes to sensors attached to board
 
  JoySt.XAxis = 127;
  JoySt.YAxis = 127;
  JoySt.Buttons = 0;
  inputs_setup();
}
const int da_start = 2;
const int da_num = 4;
static uint8_t da_inputs = 0;
void inputs_setup(void) {
  for(int i = 0; i < da_num; i++) {
    pinMode(da_start + i, INPUT_PULLUP);
  }
  da_inputs = inputs_read();
}
uint8_t inputs_read(void)
{
  uint8_t da_samp = 0;
  for(int i = 0; i < da_num; i++) {
    bitWrite(da_samp, i, (digitalRead(da_start + i) ? 0 : 1));
  }
  return da_samp;
}
void loop()
{
  task_led_toggle();
  task_inputs();
  task_serial_read();
}
void task_inputs(void)
{
  static uint32_t last;
  uint32_t now = millis();
  if(now - last > 5) {
    last = now;
    uint8_t da_samp = inputs_read();
    uint8_t toggle;
    da_samp = debounce(da_samp, &toggle);
    if(da_samp != da_inputs) {
      da_inputs = da_samp;
      //Serial.print("Inputs: ");
      //Serial.println(da_inputs, BIN);
    }
    // Now do the USB HID magic...
    // NB: every 5ms max
    // JoySt.XAxis = 127 + N64Controller.GetStick_x();
    // JoySt.YAxis = 127 + N64Controller.GetStick_y();
    // map first two buttons to up and down for testing
    if(da_samp & 0x01) // up
      JoySt.XAxis = 0;
    else if( da_samp & 0x02) // down
      JoySt.XAxis = 255;
    else
      JoySt.XAxis = 127;
    // leave Y centred for now
    JoySt.YAxis = 127;
    JoySt.Buttons = da_samp;
    Joystick.setState(&JoySt);
  }
}
void task_led_toggle(void)
{
  static uint32_t last;
  static bool on = false;
  uint32_t now = millis();
  if(now - last > 1000) {
    last = now;
    // Serial.println("Hello world");  // Print "Hello World" to the Serial Monitor
    // Serial1.println("Hello!");  // Print "Hello!" over hardware UART
    if(on){
      digitalWrite(RXLED, LOW);  // set the LED on
      TXLED0; //TX LED is not tied to a normally controlled pin
    } else {
      digitalWrite(RXLED, HIGH);    // set the LED off
      TXLED1;
    }
    on = !on;
  }
}
void task_serial_read(void) {
  // TODO
}
/*
* http://www.compuphase.com/electronics/debouncing.htm
*/
unsigned char debounce(unsigned char sample, unsigned char *toggle)
{
    static unsigned char state, cnt0, cnt1;
    unsigned char delta;
    delta = sample ^ state;
    cnt1 = (cnt1 ^ cnt0) & delta;
    cnt0 = ~cnt0 & delta;
    *toggle = delta & ~(cnt0 | cnt1);
    state ^= *toggle;
    return state;
}
</syntaxhighlight>
</div>
=== Success!!!! ===
I now have the holy grail of full Arduino IDE and APIs for with HID joypad on the Pro Micro clone - all working and tested. --[[User:Msemtd|Michael Erskine]] ([[User talk:Msemtd|talk]]) 15:38, 28 August 2015 (UTC)
=== Joypad code now on Github ===
The USB HID Joypad code is now in Github.
https://github.com/msemtd/promicro-joypad
You will need to edit some of the USB HID files in the Arduino core of 1.6.5 (ask for details). In time I should probably create a completely separate board profile but that's a lot of work! --[[User:Msemtd|Michael Erskine]] ([[User talk:Msemtd|talk]]) 09:42, 1 September 2015 (UTC)
=== Wired into Defender Control Panel ===
Direct soldering to 8-way Alarm cable x 2 + 1 GND wire and mounted in Spencer's tiny 3D printed case. Replaces a USB dancemat controller that I was never 100% happy with!
<gallery widths=300px heights=300px>
File:Promicro-wiring-direct.png|Direct soldering
File:Promicro-halfwired.png|Half-wired
File:Promicro-wired-digital.png|all digital inputs
File:Promicro-beautiful.png|in 3D printed case
File:Promicro-replacing-this.png|Replacing this mess
</gallery>
=== Large-style Pro Micro board ===
I have taken delivery of another 10 boards at a cost of £2.35 each (including postage). --[[User:Msemtd|Michael Erskine]] ([[User talk:Msemtd|talk]]) 09:30, 4 September 2015 (UTC)
These are the same technical specification and functionally equivalent however are slightly larger on a PCB of 23 x 40 mm, the bigger ATMEGA32U4 package, and a Mini-USB socket rather than a Micro-USB socket.
<gallery widths=500px heights=500px>
File:Pro-micro-3-board-types.png|Genuine Arduino Micro, Pro Micro Large, Pro Micro
File:Pro-micro-large-wired.png | Wired with 8x digital inputs on each side + GND
</gallery>
== ProMicro Neopixel ==
Code for neopixel test using simplest possible setup
<div style ="height:200px;overflow-x:hidden;overflow-y:auto;border: 4px solid green;">
<syntaxhighlight lang="cpp" line="GESHI_FANCY_LINE_NUMBERS">
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif
#define PIN            21
#define NUMPIXELS      1
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
// TODO serial comms not interfering with the pixel timing at all
// allow commands to set brightness as hex value 00 - FF
// allow commands to set colour as RGB hex value 000000 - FFFFFF
// flashing?
void setup() {
  pixels.begin();
}
void loop() {
  pixels.setBrightness(10); 
  for(int i=0;i<NUMPIXELS;i++){
    pixels.setPixelColor(i, pixels.Color(10,10,10));
    pixels.show();
    delay(1000);
    pixels.setPixelColor(i, pixels.Color(0,0,0));
    pixels.show();
    delay(500);
  }
  rainbow(25);
}
void rainbow(uint8_t wait) {
  uint16_t i, j;
  for(j=0; j<256; j++) {
    for(i=0; i<pixels.numPixels(); i++) {
      pixels.setPixelColor(i, Wheel((i+j) & 255));
    }
    pixels.show();
    delay(wait);
  }
}
// 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) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
</syntaxhighlight>
</div>
[[Category:Arduino]]
[[Category:Projects]]

Latest revision as of 16:07, 7 February 2019

ATMEGA32U4
[[{{{image}}}|border|frameless|220px|center]]
Primary Contact Michael Erskine
Created {{{created}}}
Completed {{{completeddate}}}
Dormant {{{dormantdate}}}
Version {{{version}}}
Members {{{members}}}
Manufacturer {{{manufacturer}}}
Model {{{model}}}
Location [[{{{location}}}]]
GitHub / Repo {{{repo}}}
Status In Progress
Type Members Project
Live Status {{{livestatus}}}
QR code

Many hackers wish to produce a USB device that presents itself as a HID joypad, keyboard, or mouse to a PC or Pi to provide interesting interactions and I/O opportunities in a "standardised" manner. The Arduino Micro and more recently the Leonardo use a micro with an inbuilt USB peripheral device that can be repurposed directly. Previously the Arduino boards used a second small micro or dedicated USB chip (essentially another micro) to perform the USB-serial task but the cost of this additional device was high (often more than the micro itself) and that essential USB device feature soon found itself integrated into a number of Atmel chips. This was an opportunity for the Arduino project to divorce itself from a massive dependence on FTDI (in good time for #FTDIGATE !!) and for hackers to get involved with the delights of the at90usb82, atmega16u2, etc. as secondary processors for USB comms.

Time rolls on and the excitement of the brilliant but non-open Minimus project dies down to find a number of crazy-cheap options where the USB chip is the main chip. The Atmega32U4 can be found on the Arduino Micro (currently for about £20) but also on the wonderful Teensy 2.0 and some really cheap little "Pro Micro" boards from China that at £4 each are cheaper than buying just the chip from here in the UK (in reasonable quantities). Myself (Michael E) and Spencer have ordered some of these bonkers-cheap units for initial testing and evaluation. They would appear to be clones of the Sparkfun Pro Micro https://www.sparkfun.com/products/12640

Info Dump

Initial Works for DELIVERY 1

  • board inspection: -
    • what is included other than the MCU and a 16MHz crystal?
    • what is missing other than the ICSP header?
  • programming the board as an Arduino with Arduino IDE
  • programming with dfu-programmer and avr-gcc, avr-libc, etc.
  • what bootloader is provided? The Teensy 2.0 HALFKAY?

Chip markings (from ebay photos until we receive our first delivery)

   ATMEL
   MEGA32U4
   -MU
   1448E    TH
   A2N7XA

Initial risks and mitigations: -

  • not a real ATMEL chip or bad batch/revision
  • closer inspection of chip markings and initial firmware tests
  • check JTAG IDs and Device Identification Register (26.3.2 in datasheet)
  • bad oscillator circuitry or configuration
  • pinout mapping for Arduino/teensy/Micro


    J1  |USBu|    
   TX0          RAW
   RX1          GND
   GND          RST
   GND          VCC
     2          A3
     3          A2
     4          A1
     5          A0
     6          15
     7          14
     8          16
     9          10
  +----------------+

Michael's USB-HID Work

Origins: -

New project - very similar...


Test for ProMicro with 8 inputs and keyboard output: -

static uint8_t bprev;
static uint8_t bnew;

const int pmin = 2;
const int pmax = 9;


void setup() {
  
  for(int i = pmin; i <= pmax; i++){
    pinMode(i, INPUT_PULLUP);
  }
  Serial.begin(9600);
  Keyboard.begin();
  bprev = bnew = btn_read();
}

void loop() {
  bnew = btn_read();
  if(bnew != bprev){
    Keyboard.write('z');
    Serial.print("btns = ");
    Serial.println(bnew, HEX);
    bprev = bnew;
  }
  // force change with any serial input
  if(Serial.available() > 0) {
      int b = Serial.read();
      Serial.print("RX: ");
      Serial.println(b, DEC);
      bprev = ~bprev;
  }
}

uint8_t btn_read(void) {
  uint8_t v = 0;
  for(int i = pmin; i <= pmax; i++){
    bitWrite(v, i-pmin, digitalRead(i));
  }  
  return v;  
}


Test for ProMicro with 8 inputs, debounce, multitasking and serial output: -

/* Pro Micro Test Code
   by: Nathan Seidle
   modified by: Jim Lindblom
   SparkFun Electronics
   date: September 16, 2013
   license: Public Domain - please use this code however you'd like.
   It's provided as a learning tool.

   This code is provided to show how to control the SparkFun
   ProMicro's TX and RX LEDs within a sketch. It also serves
   to explain the difference between Serial.print() and
   Serial1.print().

   modified by: Michael Erskine
   Nottingham Hackspace
   date: August 28th, 2015
   Added digital inputs from 2-9 with debounce and simple multitasking
   
*/

int RXLED = 17;  // The RX LED has a defined Arduino pin
// The TX LED was not so lucky, we'll need to use pre-defined
// macros (TXLED1, TXLED0) to control that.
// (We could use the same macros for the RX LED too -- RXLED1,
//  and RXLED0.)

void setup()
{
  pinMode(RXLED, OUTPUT);  // Set RX LED as an output
  // TX LED is set as an output behind the scenes

  Serial.begin(9600); //This pipes to the serial monitor
  Serial1.begin(9600); //This is the UART, pipes to sensors attached to board

  inputs_setup();
}

const int da_start = 2;
const int da_num = 4;
static uint8_t da_inputs = 0;

void inputs_setup(void) {
  for(int i = 0; i < da_num; i++) {
    pinMode(da_start + i, INPUT_PULLUP);
  }
  da_inputs = inputs_read();
}

uint8_t inputs_read(void)
{
  uint8_t da_samp = 0;
  for(int i = 0; i < da_num; i++) {
    bitWrite(da_samp, i, (digitalRead(da_start + i) ? 0 : 1));
  }
  return da_samp;
}

void loop()
{
  task_led_toggle();
  task_inputs();
  task_serial_read();
}

void task_inputs(void)
{
  static uint32_t last;
  uint32_t now = millis();
  if(now - last > 5) {
    last = now;
    uint8_t da_samp = inputs_read();
    uint8_t toggle;
    da_samp = debounce(da_samp, &toggle);
    if(da_samp != da_inputs) {
      da_inputs = da_samp;
      Serial.print("Inputs: ");
      Serial.println(da_inputs, BIN);
    }
  }
}

void task_led_toggle(void)
{
  static uint32_t last;
  static bool on = false;
  uint32_t now = millis();
  if(now - last > 1000) {
    last = now;
    // Serial.println("Hello world");  // Print "Hello World" to the Serial Monitor
    // Serial1.println("Hello!");  // Print "Hello!" over hardware UART
    if(on){
      digitalWrite(RXLED, LOW);   // set the LED on
      TXLED0; //TX LED is not tied to a normally controlled pin
    } else {
      digitalWrite(RXLED, HIGH);    // set the LED off
      TXLED1;
    }
    on = !on;
  }
}

void task_serial_read(void) {
  // TODO

}

/*
 * http://www.compuphase.com/electronics/debouncing.htm
 */
unsigned char debounce(unsigned char sample, unsigned char *toggle)
{
    static unsigned char state, cnt0, cnt1;
    unsigned char delta;

    delta = sample ^ state;
    cnt1 = (cnt1 ^ cnt0) & delta;
    cnt0 = ~cnt0 & delta;

    *toggle = delta & ~(cnt0 | cnt1);
    state ^= *toggle;

    return state;
}


Test for ProMicro with USB HID joystick, 8 inputs, debounce, multitasking and serial output (NB: needs mods to Arduino core USBAPI.h and HID.cpp in \arduino-1.6.5-r2\hardware\arduino\avr\cores\arduino): -

/* Pro Micro Test Code
   by: Nathan Seidle
   modified by: Jim Lindblom
   SparkFun Electronics
   date: September 16, 2013
   license: Public Domain - please use this code however you'd like.
   It's provided as a learning tool.

   This code is provided to show how to control the SparkFun
   ProMicro's TX and RX LEDs within a sketch. It also serves
   to explain the difference between Serial.print() and
   Serial1.print().

   modified by: Michael Erskine
   Nottingham Hackspace
   date: August 28th, 2015
   Added digital inputs from 2-9 with debounce and simple multitasking
   
*/

int RXLED = 17;  // The RX LED has a defined Arduino pin
// The TX LED was not so lucky, we'll need to use pre-defined
// macros (TXLED1, TXLED0) to control that.
// (We could use the same macros for the RX LED too -- RXLED1,
//  and RXLED0.)

// Joystick State
static JoyState_t JoySt;

void setup()
{
  pinMode(RXLED, OUTPUT);  // Set RX LED as an output
  // TX LED is set as an output behind the scenes

  Serial.begin(9600); //This pipes to the serial monitor
  Serial1.begin(9600); //This is the UART, pipes to sensors attached to board
  
  JoySt.XAxis = 127;
  JoySt.YAxis = 127;
  JoySt.Buttons = 0;

  inputs_setup();
}

const int da_start = 2;
const int da_num = 4;
static uint8_t da_inputs = 0;

void inputs_setup(void) {
  for(int i = 0; i < da_num; i++) {
    pinMode(da_start + i, INPUT_PULLUP);
  }
  da_inputs = inputs_read();
}

uint8_t inputs_read(void)
{
  uint8_t da_samp = 0;
  for(int i = 0; i < da_num; i++) {
    bitWrite(da_samp, i, (digitalRead(da_start + i) ? 0 : 1));
  }
  return da_samp;
}

void loop()
{
  task_led_toggle();
  task_inputs();
  task_serial_read();
}

void task_inputs(void)
{
  static uint32_t last;
  uint32_t now = millis();
  if(now - last > 5) {
    last = now;
    uint8_t da_samp = inputs_read();
    uint8_t toggle;
    da_samp = debounce(da_samp, &toggle);
    if(da_samp != da_inputs) {
      da_inputs = da_samp;
      //Serial.print("Inputs: ");
      //Serial.println(da_inputs, BIN);
    }

    // Now do the USB HID magic...
    // NB: every 5ms max
    // JoySt.XAxis = 127 + N64Controller.GetStick_x();
    // JoySt.YAxis = 127 + N64Controller.GetStick_y();
    // map first two buttons to up and down for testing
    if(da_samp & 0x01) // up
      JoySt.XAxis = 0;
    else if( da_samp & 0x02) // down
      JoySt.XAxis = 255;
    else 
      JoySt.XAxis = 127;
    // leave Y centred for now
    JoySt.YAxis = 127;
    JoySt.Buttons = da_samp;
    Joystick.setState(&JoySt);
  }
}

void task_led_toggle(void)
{
  static uint32_t last;
  static bool on = false;
  uint32_t now = millis();
  if(now - last > 1000) {
    last = now;
    // Serial.println("Hello world");  // Print "Hello World" to the Serial Monitor
    // Serial1.println("Hello!");  // Print "Hello!" over hardware UART
    if(on){
      digitalWrite(RXLED, LOW);   // set the LED on
      TXLED0; //TX LED is not tied to a normally controlled pin
    } else {
      digitalWrite(RXLED, HIGH);    // set the LED off
      TXLED1;
    }
    on = !on;
  }
}

void task_serial_read(void) {
  // TODO

}

/*
 * http://www.compuphase.com/electronics/debouncing.htm
 */
unsigned char debounce(unsigned char sample, unsigned char *toggle)
{
    static unsigned char state, cnt0, cnt1;
    unsigned char delta;

    delta = sample ^ state;
    cnt1 = (cnt1 ^ cnt0) & delta;
    cnt0 = ~cnt0 & delta;

    *toggle = delta & ~(cnt0 | cnt1);
    state ^= *toggle;

    return state;
}

Success!!!!

I now have the holy grail of full Arduino IDE and APIs for with HID joypad on the Pro Micro clone - all working and tested. --Michael Erskine (talk) 15:38, 28 August 2015 (UTC)


Joypad code now on Github

The USB HID Joypad code is now in Github.

https://github.com/msemtd/promicro-joypad

You will need to edit some of the USB HID files in the Arduino core of 1.6.5 (ask for details). In time I should probably create a completely separate board profile but that's a lot of work! --Michael Erskine (talk) 09:42, 1 September 2015 (UTC)

Wired into Defender Control Panel

Direct soldering to 8-way Alarm cable x 2 + 1 GND wire and mounted in Spencer's tiny 3D printed case. Replaces a USB dancemat controller that I was never 100% happy with!

Large-style Pro Micro board

I have taken delivery of another 10 boards at a cost of £2.35 each (including postage). --Michael Erskine (talk) 09:30, 4 September 2015 (UTC)

These are the same technical specification and functionally equivalent however are slightly larger on a PCB of 23 x 40 mm, the bigger ATMEGA32U4 package, and a Mini-USB socket rather than a Micro-USB socket.

ProMicro Neopixel

Code for neopixel test using simplest possible setup

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN            21
#define NUMPIXELS      1
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

// TODO serial comms not interfering with the pixel timing at all
// allow commands to set brightness as hex value 00 - FF
// allow commands to set colour as RGB hex value 000000 - FFFFFF
// flashing?

void setup() {
  pixels.begin();
}



void loop() {
  pixels.setBrightness(10);  
  for(int i=0;i<NUMPIXELS;i++){
    pixels.setPixelColor(i, pixels.Color(10,10,10));
    pixels.show();
    delay(1000);
    pixels.setPixelColor(i, pixels.Color(0,0,0));
    pixels.show();
    delay(500);
  }
  rainbow(25);
}

void rainbow(uint8_t wait) {
  uint16_t i, j;
  for(j=0; j<256; j++) {
    for(i=0; i<pixels.numPixels(); i++) {
      pixels.setPixelColor(i, Wheel((i+j) & 255));
    }
    pixels.show();
    delay(wait);
  }
}

// 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) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}