I bought a DeskCycle (https://deskcycle.com/products/deskcycle-under-desk-bike) so I can mindlessly cycle at home while working on other tasks. (I’m not 100% sure of the health impact but it doesn’t really matter for now) Of course, it came with a display that let you track your speed, distance, and etc. it also came with a 3.5mm aux audio cable that you can use if you wanted to have the tracker display on your desk. I had the idea of using the Deskcycle to walk or run in games, like Just Cause 3 or any similar game has good visuals. First thing I did is to Google to see if anyone had interfaced Arduino with DeskCycle and someone had. Neave Engineering blog (https://neave.engineering/?s=deskcycle) has three articles on interfacing DeskCycle with an Arduino. One of the articles (https://neave.engineering/2015/04/03/arduino-speedometer-for-the-deskcycle/) mentions that there is a switch that closes as cycle revolutions happen, which made my job easier. Basically, the input from 3.5mm jack can be treated like button input. This is where the Thotcon (https://thotcon.org/) 0x8 badge comes in. Thotcon 0x8 badge is built on Arduino Leonardo, which can also work as a keyboard! (Teensy would work too but I had a thotcon badge sitting around) A hackaday.io project post had the instructions to reprogram the badge via ICSP header (https://hackaday.io/project/21797-thotcon-0x8-badge/log/59432-badge-hacking-update). It involves connecting AVR programmer then burning bootloader. After that, the badge can be reprogrammed via USB. At this point, I hadn’t read the whole article from Neave Engineering. I spent hours trying to make the badge press and hold ‘w’ key (to walk forward in a game) in a bunch of different ways. For some reason, key presses would stop/weren’t continuous and I had other issues too. I went back and looked at the Neave Engineering post again and decided to reuse that code. Neave Engineering code can be found here: https://github.com/kneave/dcspeedo/blob/master/speedo/speedo.ino The code comments are very useful! I cut my 3.5mm cable, found the two wires that connect when a cycle/revolution happens and attached one to ground and one to pin 12 (var name is trigger in the code). As far as I can tell, the bottom row of pins in Thotcon 0x8 badge are all ground pins, although, I might be wrong. I didn’t closely test all of them. Here’s my badge, with DeskCycle output pins attached to pin 12 and ground:
Here’s my modified code that does a keypress: #include <Keyboard.h> const float pi = 3.14159265; const float inchesPerMile = 63360; const int wheelSize = 26; const float gearRatio = 2.75; const float wheelCircumference = wheelSize * pi; long lastTriggerTime = 0; long currentTriggerTime = 0; long triggerInterval = 0; int lastTriggerValue = 0; int triggerValue = 0; int trigger = 12; float cadence = 0; float currentSpeed = 0; void setup() { pinMode(trigger, INPUT); // set pin to input digitalWrite(trigger, HIGH); // turn on pullup resistors Keyboard.begin(); cli();//stop interrupts TCCR1A = 0;// set entire TCCR2A register to 0 TCCR1B = 0;// same for TCCR2B TCNT1 = 0;//initialize counter value to 0 OCR1A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256) TCCR1A |= (1 << WGM01); TCCR1B |= (1 << CS01) | (1 << CS00); TIMSK1 |= (1 << OCIE1A); sei();//allow interrupts lastTriggerTime = millis(); }//end setup ISR(TIMER1_COMPA_vect) { triggerValue = digitalRead(trigger); triggerValue = triggerValue == 0 ? 1 : 0; currentTriggerTime = millis(); triggerInterval = currentTriggerTime - lastTriggerTime; if(triggerInterval >= 2000) { cadence = 0; currentSpeed = 0; } if(lastTriggerValue != triggerValue) { lastTriggerValue = triggerValue; if(triggerValue == 1) { lastTriggerTime = currentTriggerTime; cadence = 60000 / triggerInterval; float rph = cadence * 60; float wheelRph = rph * gearRatio; float inchesPerHour = wheelCircumference * wheelRph; currentSpeed = inchesPerHour / inchesPerMile; } } } void loop() { //not checking to see if w is pressed already since this code is not causing any issue. if (currentSpeed > 0){ Keyboard.press('w'); } else { Keyboard.releaseAll(); } } I removed serial output stuff since it wasn’t needed. I only care about the speed. If speed is higher than 0, then keep pressing w, else release all the keys. If there hasn’t been a cycle/revolution in more than 2 seconds, speed is set to 0.