Hello i have an controller with 8 buttons an 1 incremental encoder and i want to connect it to my android headunit. I came as far as seeing the button i press in serial monitor, however i have no idea how to code the encoder so i can turn up and down my volume.
Which Arduino does the 'encoder' use ?
It is all connected to an arduino uno
Hi @philki99
welcome to the arduino-forum.
you should take 20 minutes time to speed up finishing your project minimum 200 minutes
by reading
what is an "android headunit" ??
what interfaces does this headunit have?
serial?
I2C?
SPI?
USB?
WiFi?
bluetooth?
with a single encoder on an arduino uno I recommend the newEncoder-library
best regards Stefan
It is a joying 10.1 car radio for an e90, that runs on android .I don’t think it has l2c or spi but it has wifi Bluetooth and usb. My initial thought was connecting it through usb.
Thank you I will try and use that library, however i still don’t know how to code the Programm for encrypting the encoder
If you want efficient help you have to describe the wanted functionality with a much higher precision.
What shall the buttons do?
What shall the encoder do?
shall your buttons and encoder be a generalised remote-control that replaces touching the screen for all and every app that is running on your android-device??
or
do you want to use it especcially for the "radio-app" ?
Is your device based on android but it is only a radio?
Of course if you look through the world how thing scan be connected together a lot of things are possible. Connecting Alexa or google-home to whatever smarthome lamps. microwave, washing-machine etc.
But this does not mean that this is as easy to to as connecting a smartphone to your PC or to a bluetooth-speaker
This customer-easiness in pairing a smartphone to a bluetooth-speaker is realised by a big amout of prelimary software development from the manufacturer of the device to make it work.
So you it might be an easier way to use a ready to use smartphone app that acts as a remote to things like a tablet or PC
But this depends on what you want to do. I'm pretty sure you have not read the how to get the best out of this forum.
If you would have read it you would already post more detailed information.
best regards Stefan
Ok so the problem I’m trying to solve is that I dont have a volume knob (on my headunite that is operating on android), so I bought a Chinese idrive controller to maintain the oem look. The 8 buttons should do what’s on them( it’s disassemble and the middle button should pause and play) and the encoder should be the volume knob. I only use apple car play( so it’s a CarPlay app) so I don’t expect a button like option to have any function. The controller works with 12v(the orange cabel coming out from underneath is for light). I connected all the pins from the buttons (closed till pressed) with the arduino. Then I connected the 2 pins of the encoder( I think the third one is ground that’s why I connected gnd with the gnd from the arduino), but I have no idea how to code the encoder. The 8 buttons are working in the serial monitor. One of the pictures is a data sheet of the encoder the other on is the current setup
I'm willing to help if you follow the details given in this description
what is so hard about reading?
best regards Stefan
I’ve already read it, this is the code on my arduino UNO it was generated with the help of chatgpt. I already Writen everything I know.
The goal is to make it work on ma car radio that is running on android, connected to the arduino via usb. It’s main purpose is the volume knob, it should work in the apple car play app
#include <Keyboard.h>
// Tasten
const int pinMenu = 2;
const int pinPausePlay = 3;
const int pinBack = 4;
const int pinTEL = 5;
const int pinOption = 6;
const int pinMap = 7;
const int pinNextSong = 8;
const int pinPrevSong = 9;
// Inkrementalgeber
const int pinEncoderA = 10;
const int pinEncoderB = 11;
int lastEncoded = 0;
long encoderValue = 0;
void setup() {
// Tasten als Eingänge konfigurieren
pinMode(pinMenu, INPUT_PULLUP);
pinMode(pinPausePlay, INPUT_PULLUP);
pinMode(pinBack, INPUT_PULLUP);
pinMode(pinTEL, INPUT_PULLUP);
pinMode(pinOption, INPUT_PULLUP);
pinMode(pinMap, INPUT_PULLUP);
pinMode(pinNextSong, INPUT_PULLUP);
pinMode(pinPrevSong, INPUT_PULLUP);
// Inkrementalgeber als Eingänge konfigurieren
pinMode(pinEncoderA, INPUT_PULLUP);
pinMode(pinEncoderB, INPUT_PULLUP);
// USB-Tastatur initialisieren
Keyboard.begin();
// Serielle Kommunikation starten
Serial.begin(9600);
}
void loop() {
// Menü-Taste
if (digitalRead(pinMenu) == LOW) {
Serial.println("Menu-Taste gedrückt");
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('m');
delay(50);
Keyboard.releaseAll();
}
// Pause/Play-Taste
if (digitalRead(pinPausePlay) == LOW) {
Serial.println("Pause/Play-Taste gedrückt");
Keyboard.press(KEY_SPACE);
delay(50);
Keyboard.releaseAll();
}
// Zurück-Taste
if (digitalRead(pinBack) == LOW) {
Serial.println("Zurück-Taste gedrückt");
Keyboard.press(KEY_LEFT_ARROW);
delay(50);
Keyboard.releaseAll();
}
// TEL-Taste
if (digitalRead(pinTEL) == LOW) {
Serial.println("TEL-Taste gedrückt");
Keyboard.press(KEY_T);
delay(50);
Keyboard.releaseAll();
}
// Option-Taste
if (digitalRead(pinOption) == LOW) {
Serial.println("Option-Taste gedrückt");
Keyboard.press(KEY_O);
delay(50);
Keyboard.releaseAll();
}
// Map-Taste
if (digitalRead(pinMap) == LOW) {
Serial.println("Map-Taste gedrückt");
Keyboard.press(KEY_M);
delay(50);
Keyboard.releaseAll();
}
// Nächster Song-Taste
if (digitalRead(pinNextSong) == LOW) {
Serial.println("Nächster Song-Taste gedrückt");
Keyboard.press(KEY_MEDIA_NEXT_TRACK);
delay(50);
Keyboard.releaseAll();
}
// Vorheriger Song-Taste
if (digitalRead(pinPrevSong) == LOW) {
Serial.println("Vorheriger Song-Taste gedrückt");
Keyboard.press(KEY_MEDIA_PREV_TRACK);
delay(50);
Keyboard.releaseAll();
}
// Inkrementalgeber auslesen
int MSB = digitalRead(pinEncoderA);
int LSB = digitalRead(pinEncoderB);
int encoded =
sigh! chatGPT
The code that was generated by chatGPT is incomplete.
Even your application is too complex to get working code from a short description .
My estimation is it will be less work to ask human users directly
compared to correct AI-generated code
best regards Stefan
what information would you need for a code like that, so i know what i have to search for
You need the "information" that the experienced users here will help you as soon as you show own effort in writing code.
Using chatGPT is the opposite of own effort.
You need the "information" to ask specific questions by using a certain pattern.
This pattern is:
posting your actual code as a code-section (you already know how this works which is very good)
writing what the code is doing
writing how what the code does is different from what you want the code to do
providing a hand-drawn schematic
do you understand ? a hand-drawn schematic shoot a picture with your smartphone from the handdrawn schematic and post this picture
do NOT post a frizzy picture!
all the things you can read in this tutorial that I am posting for the third time now
basic knowledge how c++-coding works
Take a look into this tutorial:
It is easy to understand and has a good mixture between explaining important concepts and example-codes to get you going. So give it a try and report your opinion about this tutorial.
Knowledge how to use a rotary encoder-library
I recommend the NewEncoder-library
best regards Stefan
Hello
I tried to learn a bit to code, look into the new encoder library and used the example and coded my own buttons,
However i came across a few problems
-The Encoder works partialy, it does what it needs to but sometimes just rises to max oder goes the other way im rotating it. ( I hope someone can help me with that,it is the most imprortant problem that i have)
The serial monitor goes like
Volume 1
Volume 2
Volume 6
Volume 7
Volume 6
-i've read that the analog pins would be better for the Encoder, however everytime i try to code from digital to analog pin the encoder fails to start.
-last problem, my arduino wont go to dfu so i can make it a keyboard(it is a mega16u2,now ill buy a second on to try to code it with the second one)(i try to make it a keyboard as input for the android radio)
Here is my code an my setup
#include "NewEncoder.h"
const int buttonPin1 = 4;
const int buttonPin2 = 5;
const int buttonPin3 = 6;
const int buttonPin4 = 7;
const int buttonPin5 = 8;
const int buttonPin6 = 9;
const int buttonPin7 = 10;
const int buttonPin8 = 11;
NewEncoder encoder(A2, A3, 0, 40, 4, HALF_PULSE);
int16_t prevEncoderValue;
void setup() {
pinMode(buttonPin1, INPUT_PULLUP);
pinMode(buttonPin2, INPUT_PULLUP);
pinMode(buttonPin3, INPUT_PULLUP);
pinMode(buttonPin4, INPUT_PULLUP);
pinMode(buttonPin5, INPUT_PULLUP);
pinMode(buttonPin6, INPUT_PULLUP);
pinMode(buttonPin7, INPUT_PULLUP);
pinMode(buttonPin8, INPUT_PULLUP);
NewEncoder::EncoderState state;
Serial.begin(9600);
delay(1000);
Serial.println("Starting");
if (!encoder.begin()) {
Serial.println("Encoder Failed to Start");
while (1) {
yield();
}
} else {
encoder.getState(state);
Serial.print("Encoder Successfully Started at value = ");
prevEncoderValue = state.currentValue;
Serial.println(prevEncoderValue);
}
}
void loop() {
{
if (digitalRead(buttonPin1) == LOW) {
Serial.println("Tel");
}
if (digitalRead(buttonPin2) == LOW) {
Serial.println("Menu");
}
if (digitalRead(buttonPin3) == LOW) {
Serial.println("Map");
}
if (digitalRead(buttonPin4) == LOW) {
Serial.println("Prev");
}
if (digitalRead(buttonPin5) == LOW) {
Serial.println("Next");
}
if (digitalRead(buttonPin6) == LOW) {
Serial.println("Pause/Play");
}
if (digitalRead(buttonPin7) == LOW) {
Serial.println("Back");
}
if (digitalRead(buttonPin8) == LOW) {
Serial.println("Option");
}
delay(180);
}
int16_t currentValue;
NewEncoder::EncoderState currentEncoderState;
if (encoder.getState(currentEncoderState)) {
Serial.print("Volume: ");
currentValue = currentEncoderState.currentValue;
if (currentValue != prevEncoderValue) {
Serial.println(currentValue);
prevEncoderValue = currentValue;
} else
switch (currentEncoderState.currentClick) {
case NewEncoder::UpClick:
Serial.println("VOL MAX");
break;
case NewEncoder::DownClick:
Serial.println("VOL LOW");
break;
default:
break;
}
}
}
where did you read that?
The documentation of the newEncoder-library says
Interrupt-driven rotary encoder library.
Two interrupt-capable pins are required for each encoder connected.
On an arduino uno only IO-pin 2 and IO-pin 3 are interrupt-capable
what is a "dfu"?
This picture of you
clearly shows an original arduino-uno which has a atmel328P microcontroller.
it is very important that you clearly specify exactly which microcontroller you use because their internal hardware is always different.
at the moment you are using 10 io-pins.
Are you planning to use more than 10 io-pins or is this all?
A microcontroller with native USB might be better suited.
Again this is a reason why you should write better 20 sentences more than too less.
Only exception if you enjoy buying new microcontrollers and get used to the different types of microcontrollers
If you plan to use more than one rotary-encoder you should use a microcontroller with more interrupt-capable io-pins
best regards Stefan
I don’t remember where I read it but ok thank you that explains why it the analog pins aren’t working.
DFU, I’m not completely sure but I think it means something like Device Firmware Update, so I can flash it to be a keyboard.
The atmega16u2 ist the controller which connects the the atmel328P with the usb port(actually I bought it from AliExpress for 5 bucks)
The 10io pins are all that I’m using.
What microcontroller would you advise me?
Ok but back to the main issue, should I try to solder on another encoder or do you see any code problem?
Again the problem is that the encoder works only partly , it throws random numbers in sometimes.
If you connect the rotary-encoder to IO-pins 2 and 3 which are the only interrupt-capable IO-pins on an arduino the encoder should work very reliable.
Still this is an unprecise description of what is happening.
Imagine a doctor shall give you an exact diagnoses by listening to one sentence of you
"I'm feeling bad" and now the doctor shall say a precise diagnoses. Not possible.
Same with "encoder throws random numbers sometimes"
Did you test your encoder with the demo-code that comes with the NewEncoder-library?
If the result is somehow non-regular you should post two things: the actual code and what numbers are printed to the serial monitor.
The 16u2 is used for flashing the Atmel 328P. I'm not really sure but you should'nt reflash the 16u2 co-processor.
best regards Stefan
ok so here is the code and a picture of the serial monitor.
Im rotating counter clock wise till the red line, then i rotate clockwise.
Ive used the demo code and as long as i put half_pulse instead of full_pulse it works as shown in the picture.
In the code, the number should go one by one from up or down from 0 up to 40 depending on the direction of rotation. If i rotate slow and steady it looks like in the picture, however as soon as i pick up speed it seems like it makes a break.
#include "NewEncoder.h"
const int buttonPin1 = 4;
const int buttonPin2 = 5;
const int buttonPin3 = 6;
const int buttonPin4 = 7;
const int buttonPin5 = 8;
const int buttonPin6 = 9;
const int buttonPin7 = 10;
const int buttonPin8 = 11;
NewEncoder encoder(2, 3, 0, 40, 4, HALF_PULSE);
int16_t prevEncoderValue;
void setup() {
pinMode(buttonPin1, INPUT_PULLUP);
pinMode(buttonPin2, INPUT_PULLUP);
pinMode(buttonPin3, INPUT_PULLUP);
pinMode(buttonPin4, INPUT_PULLUP);
pinMode(buttonPin5, INPUT_PULLUP);
pinMode(buttonPin6, INPUT_PULLUP);
pinMode(buttonPin7, INPUT_PULLUP);
pinMode(buttonPin8, INPUT_PULLUP);
NewEncoder::EncoderState state;
Serial.begin(9600);
delay(1000);
Serial.println("Starting");
if (!encoder.begin()) {
Serial.println("Encoder Failed to Start");
while (1) {
yield();
}
} else {
encoder.getState(state);
Serial.print("Encoder Successfully Started at value = ");
prevEncoderValue = state.currentValue;
Serial.println(prevEncoderValue);
}
}
void loop() {
{
if (digitalRead(buttonPin1) == LOW) {
Serial.println("Tel");
}
if (digitalRead(buttonPin2) == LOW) {
Serial.println("Menu");
}
if (digitalRead(buttonPin3) == LOW) {
Serial.println("Map");
}
if (digitalRead(buttonPin4) == LOW) {
Serial.println("Prev");
}
if (digitalRead(buttonPin5) == LOW) {
Serial.println("Next");
}
if (digitalRead(buttonPin6) == LOW) {
Serial.println("Pause/Play");
}
if (digitalRead(buttonPin7) == LOW) {
Serial.println("Back");
}
if (digitalRead(buttonPin8) == LOW) {
Serial.println("Option");
}
delay(180);
}
int16_t currentValue;
NewEncoder::EncoderState currentEncoderState;
if (encoder.getState(currentEncoderState)) {
Serial.print("Volume: ");
currentValue = currentEncoderState.currentValue;
if (currentValue != prevEncoderValue) {
Serial.println(currentValue);
prevEncoderValue = currentValue;
} else
switch (currentEncoderState.currentClick) {
case NewEncoder::UpClick:
Serial.println("VOL MAX");
break;
case NewEncoder::DownClick:
Serial.println("VOL LOW");
break;
default:
break;
}
}
}
@gfvalvo Do you know why this is happening?
@philki99
what results do you get if you use the real original code?
I mean without the if-conditions for the buttons
best regards Stefan
The original code is pretty much the demo code from NewLibrary, but it is exactly the same
This means if you upload exactly this code
you get output of the encoder-value where the encoder-value jumps instead
of counting one by one up/down?