Anyone pro in Arduino making sketches ? (1 Viewer)

Jeff[NL]

Well-Known Member
#TeamRSR
Joined
Oct 22, 2018
Messages
298
Reaction score
350
So i am still busy completing my custom DD1 wheel. Last part is to write a sketch for Arduino so i can program a module with bluetooth for the buttons and encoders.
I tried it myself offcourse but i cant get it to work 100% somehow.

I found some sketches for other purposes and thought i could alter those but i seem to struggle to get the right output of the rotary encoder. I can get it working on bluetooth connect and buttons work but not yet the encoders.

Is there anyone here thats very smart in this stuff thats willing to help me finalizing my project ?
 

Michael

Moderator
#TeamRSR
Community Member
Joined
Sep 1, 2017
Messages
917
Reaction score
817
It's been a long time since i fiddled with that, but when you send me your draft, i can have a look tomorrow. Are you using an encoder or something like a 12-way rotary switch?

EDIT: Oh, and what Arduino are you using?
 
Last edited:

Jeff[NL]

Well-Known Member
#TeamRSR
Joined
Oct 22, 2018
Messages
298
Reaction score
350
It's been a long time since i fiddled with that, but when you send me your draft, i can have a look tomorrow. Are you using an encoder or something like a 12-way rotary switch?

EDIT: Oh, and what Arduino are you using?
This is the board i am using. Maybe it was not the smartest way to go but coudnt find any better one also regarding price.
https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide?view=all

The encoder and joystick is from Leo Bodnar http://www.leobodnar.com/shop/index.php?main_page=product_info&cPath=98_87&products_id=210 and
http://www.leobodnar.com/shop/index.php?main_page=product_info&cPath=98_75&products_id=242

I use this sketch from a atari joystick made with bleutooth. I think the basic principle is the same just different 'button box ' if you know what i mean. I adjusted the outputs in this sketch but the encoder keeps sending a signal as soon i turned it one way on the rotary. I click one time to right and it keeps sending the signal i dont know why that is.

#include <bluefruit.h>

BLEDis bledis;
BLEHidAdafruit blehid;

#define VERSION "0.1"
#define LED_ON

/*
The following I/O pins will be used as digital inputs
for each specific function.
*/
#define UP_PIN 15 // WHT
#define DOWN_PIN 7 // BLU
#define LEFT_PIN 11 // GRN
#define RIGHT_PIN 16 // BRN
#define BTN1_PIN A2
#define BTN2_PIN 27
#define BTN3_PIN A0
#define BTN4_PIN A1
#define BTN5_PIN 30 // ORG
#define BTN6_PIN A3
#define BTN7_PIN A4
#define BTN8_PIN A5

/*
The following keys are the sequence (hold, release)
for each function. Send "W" to indicate UP, and "E" when
UP is released.
*/
#define UP_KEYS "w"
#define DOWN_KEYS "s"
#define LEFT_KEYS "a"
#define RIGHT_KEYS "d"
#define BTN1_KEYS "y"
#define BTN2_KEYS "u"
#define BTN3_KEYS "i"
#define BTN4_KEYS "g"
#define BTN5_KEYS "h"
#define BTN6_KEYS "j"
#define BTN7_KEYS "k"
#define BTN8_KEYS "l"

#define DI_PIN_COUNT 12 // 12 pins used.
// #define DI_PIN_START 1 // First I/O pin.
// #define DI_PIN_END 20 // Last I/O pin.

byte myPins[DI_PIN_COUNT] = {UP_PIN, DOWN_PIN, LEFT_PIN, RIGHT_PIN, BTN1_PIN,
BTN2_PIN, BTN3_PIN, BTN4_PIN,
BTN5_PIN, BTN6_PIN, BTN7_PIN, BTN8_PIN};

char iCadeKeymap[][DI_PIN_COUNT] = {UP_KEYS, DOWN_KEYS, LEFT_KEYS, RIGHT_KEYS,
BTN1_KEYS, BTN2_KEYS, BTN3_KEYS, BTN4_KEYS,
BTN5_KEYS, BTN6_KEYS, BTN7_KEYS, BTN8_KEYS};

char iCadeDesc[][DI_PIN_COUNT] = {"Up", "Down", "Left", "Right", "Btn1",
"Btn2", "Btn3", "Btn4",
"Btn5", "Btn6", "Btn7", "Btn8"};

/* We want a very short debounce delay for an arcade controller. */
#define DI_DEBOUNCE_MS 10 // 100ms (1/10th second)

#define LED_PIN 17
//#define POWER_LED 17
#define LEDBLINK_MS 1000


/* For I/O pin status and debounce. */
unsigned int digitalStatus[DI_PIN_COUNT]; // Last set PIN mode.
unsigned long digitalDebounceTime[DI_PIN_COUNT]; // Debounce time.
//unsigned long digitalCounter[DI_PIN_COUNT]; // Times button pressed.
unsigned int digitalDebounceRate = DI_DEBOUNCE_MS; // Debounce rate.

/* For the blinking LED (heartbeat). */
unsigned int ledStatus = LOW; // Last set LED mode.
unsigned long ledBlinkTime = 0; // LED blink time.
unsigned int ledBlinkRate = LEDBLINK_MS; // LED blink rate.

unsigned int pinsOn = 0;


void setup()
{
// Just in case it was left on...
//wdt_disable();

// Initialize the serial port.
Serial.begin(115200);
Serial.println();
Serial.println("Go to your phone's Bluetooth settings to pair your device");
Serial.println("then open an application that accepts keyboard input");
Bluefruit.begin();
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
Bluefruit.setTxPower(4);
Bluefruit.setName("AtariFruitJoystick");

// Configure and Start Device Information Service
bledis.setManufacturer("Adafruit Industries");
bledis.setModel("Atari Fruit Joystick 52");
bledis.begin();

/* Start BLE HID
* Note: Apple requires BLE device must have min connection interval >= 20m
* ( The smaller the connection interval the faster we could send data).
* However for HID and MIDI device, Apple could accept min connection interval
* up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max
* connection interval to 11.25 ms and 15 ms respectively for best performance.
*/
blehid.begin();

/* Set connection interval (min, max) to your perferred value.
* Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
* min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms
*/
/* Bluefruit.setConnInterval(9, 12); */

// Set up and start advertising
startAdv();

// Docs say this isn't necessary for Uno.
//while(!Serial) { }

showHeader();

// Initialize watchdog timer for 2 seconds.
//wdt_enable(WDTO_4S);

// LOW POWER MODE!
// Pins default to INPUT mode. To save power, turn them all to OUTPUT
// initially, so only those being used will be turn on. See:
// http://www.pjrc.com/teensy/low_power.html
for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
{
pinMode(thisPin, OUTPUT);
}

// Disable Unused Peripherals
// ADCSRA = 0;

// Initialize the pins and digitalPin array.
for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
{
// Set pin to be digital input using pullup resistor.
pinMode(myPins[thisPin], INPUT_PULLUP);
// Set the current initial pin status.
digitalStatus[thisPin] = HIGH; //digitalRead(thisPin+DI_PIN_START);
// Clear debounce time.
digitalDebounceTime[thisPin] = 0;
//digitalCounter[thisPin] = 0;
}

// Set LED pin to output, since it has an LED we can use.
pinMode(LED_PIN, OUTPUT);
// pinMode(POWER_LED, OUTPUT);
// digitalWrite(POWER_LED, HIGH);

Serial.println("Ready.");

}


void startAdv(void)
{
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);

// Include BLE HID service
Bluefruit.Advertising.addService(blehid);

// There is enough room for the dev name in the advertising packet
Bluefruit.Advertising.addName();

/* Start Advertising
* - Enable auto advertising if disconnected
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
* - Timeout for fast mode is 30 seconds
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
*
* For recommended advertising interval
* https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
}


void loop()
{
// Tell the watchdog timer we are still alive.
//wdt_reset();

#ifndef LED_OFF
// LED blinking heartbeat. Yes, we are alive.
if ( (long)(millis()-ledBlinkTime) >= 0 )
{
// Toggle LED.
if (ledStatus==LOW) // If LED is LOW...
{
ledStatus = HIGH; // ...make it HIGH.
} else {
ledStatus = LOW; // ...else, make it LOW.
}
// Set LED pin status.
if (pinsOn==0) digitalWrite(LED_PIN, ledStatus);
// Reset "next time to toggle" time.
ledBlinkTime = millis()+ledBlinkRate;
}
#endif

// Check for serial data.
if (Serial.available() > 0) {
// If data ready, read a byte.
int incomingByte = Serial.read();
// Parse the byte we read.
switch(incomingByte)
{
case '?':
showStatus();
break;
default:
break;
}
}


// Loop through each Digital Input pin.
for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
{
// Read the pin's current status.
unsigned int status = digitalRead(myPins[thisPin]);

// In pin status has changed from our last toggle...
if (status != digitalStatus[thisPin])
{
blehid.keyRelease();
// Remember when it changed, starting debounce mode.
// If not currently in debounce mode,
if (digitalDebounceTime[thisPin]==0)
{
// Set when we can accept this as valid (debounce is considered
// done if the time gets to this point with the status still the same).
digitalDebounceTime[thisPin] = millis()+digitalDebounceRate;
}

// Check to see if we are in debounce detect mode.
if (digitalDebounceTime[thisPin]>0)
{
// Yes we are. Have we delayed long enough yet?
if ( (long)(millis()-digitalDebounceTime[thisPin]) >= 0 )
{
// Yes, so consider it switched.
// If pin is Active LOW,
if (status==LOW)
{
// Emit BUTTON PRESSED string.
Serial.print(iCadeDesc[thisPin]);
Serial.print(" pressed (sending ");
Serial.print(iCadeKeymap[thisPin][0]);
Serial.println(" to iCade).");
blehid.keyPress(iCadeKeymap[thisPin][0]);
//Keyboard.print(iCadeKeymap[thisPin][0]);
//digitalCounter[thisPin]++;
pinsOn++;
#ifndef LED_OFF
digitalWrite(LED_PIN, HIGH);
#endif
} else {
// Emit BUTTON RELEASED string.
Serial.print(iCadeDesc[thisPin]);
Serial.print(" released (sending ");
Serial.print(iCadeKeymap[thisPin][1]);
Serial.println(" to iCade).");
blehid.keyPress(iCadeKeymap[thisPin][1]);
//Keyboard.print(iCadeKeymap[thisPin][1]);
if (pinsOn>0) pinsOn--;
if (pinsOn==0) digitalWrite(LED_PIN, LOW);
}
// Remember current (last set) status for this pin.
digitalStatus[thisPin] = status;
// Reset debounce time (disable, not looking any more).
digitalDebounceTime[thisPin] = 0;
} // End of if ( (long)(millis()-digitalDebounceTime[thisPin]) >= 0 )

} // End of if (digitalDebounceTime[thisPin]>0)
}
else // No change? Flag no change.
{
// If we were debouncing, we are no longer debouncing.
digitalDebounceTime[thisPin] = 0;
}
} // End of (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )

// Request CPU to enter low-power mode until an event/interrupt occurs
waitForEvent();
}

void showHeader()
{
int i;
// Emit some startup stuff to the serial port.
Serial.println("Atari 2600 BlueCade by John Park for Adafruit. ");
Serial.print("Based on: iCadeTeensy ");
Serial.print(VERSION);
Serial.println(" by Allen C. Huffman (alsplace@pobox.com)");
Serial.print(DI_PIN_COUNT);
Serial.print(" DI Pins (");
for (i=0; i<DI_PIN_COUNT; i++)
{
Serial.print(myPins);
Serial.print("=");
Serial.print(iCadeDesc);
Serial.print(" ");
}
Serial.print("), ");
Serial.print(digitalDebounceRate);
Serial.println("ms Debounce.");
}


void showStatus()
{
showDigitalInputStatus();
}


void showDigitalInputStatus()
{
Serial.print("DI: ");

for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
{
// Read the pin's current status.
Serial.print(iCadeDesc[thisPin]);
Serial.print("=");
Serial.print(digitalRead(myPins[thisPin]));
Serial.print(" ");
//Serial.print(" (");
//Serial.print(digitalCounter[thisPin]);
//Serial.print(") ");
}
Serial.println("");
}

/**
* RTOS Idle callback is automatically invoked by FreeRTOS
* when there are no active threads. E.g when loop() calls delay() and
* there is no bluetooth or hw event. This is the ideal place to handle
* background data.
*
* NOTE: FreeRTOS is configured as tickless idle mode. After this callback
* is executed, if there is time, freeRTOS kernel will go into low power mode.
* Therefore waitForEvent() should not be called in this callback.
* http://www.freertos.org/low-power-tickless-rtos.html
*
* WARNING: This function MUST NOT call any blocking FreeRTOS API
* such as delay(), xSemaphoreTake() etc ... for more information
* http://www.freertos.org/a00016.html
*/
void rtos_idle_callback(void)
{
// Don't call any other FreeRTOS blocking API()
// Perform background task(s) here
}
// End of file.
 

RdMracer

Active Member
Community Member
Joined
Oct 30, 2016
Messages
102
Reaction score
68
Might be the jitter making things more difficult.
I've read about a project that adds caps to filter the rotaries to make them more accurate.
Should help you with the general setup of the encoder readout sketch too.

 

Jeff[NL]

Well-Known Member
#TeamRSR
Joined
Oct 22, 2018
Messages
298
Reaction score
350
Might be the jitter making things more difficult.
I've read about a project that adds caps to filter the rotaries to make them more accurate.
Should help you with the general setup of the encoder readout sketch too.

That might be the issue i am having thanks gonna take a good look into that.
 

Michael

Moderator
#TeamRSR
Community Member
Joined
Sep 1, 2017
Messages
917
Reaction score
817
Mmh...So this is so generic that it looks for ANY input and compares the current state to previous state... What BTN is the encoder?
Maybe you can also assign the encoder function to button presses like this:

Code:
if ((digitalRead(EncoderUp) == LOW) {               //LOW if you defined the resistors to be pulled up for the untriggered state
    Keyboard.begin();
    Keyboard.press(128); //LCtrl
    Keyboard.press(130); //LAlt
    Keyboard.press('m');
    delay(100);
    Keyboard.releaseAll();
    Keyboard.end();
    }

EncoderUp / EncoderDown as placeholder, must be defined of course.
 

Jeff[NL]

Well-Known Member
#TeamRSR
Joined
Oct 22, 2018
Messages
298
Reaction score
350
Mmh...So this is so generic that it looks for ANY input and compares the current state to previous state... What BTN is the encoder?
Maybe you can also assign the encoder function to button presses like this:

Code:
if ((digitalRead(EncoderUp) == LOW) {               //LOW if you defined the resistors to be pulled up for the untriggered state
    Keyboard.begin();
    Keyboard.press(128); //LCtrl
    Keyboard.press(130); //LAlt
    Keyboard.press('m');
    delay(100);
    Keyboard.releaseAll();
    Keyboard.end();
    }

EncoderUp / EncoderDown as placeholder, must be defined of course.
Will try that thanks
 

Users who are viewing this thread

Top