Programming Joypad with Arduino Uno R3 and HC05 (Old version)
It is a wifi remote controller built with arduino uno and HC05 wifi module. It is powered by 2 pieces of lipo batteries.
Construction
Pin Assignment
Pin | Function | remarks |
PB0 | key drive | SW20, SW30 |
PB1 | key drive | SW21, SW31 |
PB2 | key drive | SW22, SW32 |
PB3 | LED | |
PB5 | LED | UNO |
PD0 | RX | UART |
PD1 | TX | UART |
PD2 | key sense | SW2, SW20, SW21, SW22 |
PD3 | key sense | SW3, SW30, SW31, SW32 |
AREF | ADC | battery |
PB1 | ||||
^ | ||||
PB0 | < | PD2 | > | PB2 |
v | ||||
GND |
Keypad
Circuit
As shown in the diagram, there are four buttons. Each button is connecting to two signals. Red means high and black means low. PD2 is the sensing signal which is weakly pulled high. PB0 to PB3 can be either low or floating. Click the checkboxes to see how PD2 responds. The other button group is similar, except the sensing pin is changed to PD3.
Data Format
GND | GND | ||||||||||||||
PB2 | PD2 | PB0 | PB0 | PD3 | PB1 | ||||||||||
PB1 | ASCII | PB2 |
When
a button is pressed or released, this information is sent via UART.
Each 4-button group needs 3 bits to represent its state. So one byte is
enough. Data shall be sent only when change occurs.
Coding
/* main.c */
e u e a e O O O A A O };
oi i i oi ; i i ia i e o i i e ua a a
oi ai u i e i ;
oi e e u e a e ;
i a e o oi a e u oi ;
oi u o oi ; a ea u o ua
i ai
i i ;
e O ; i i a e a e ie a e o e e
ai ;
i e a e o e a e u O A ;
e O ;
u o ; o e u e o a e a e ie
i e ;
}
n m l d_st t { N, FF, N RM L, F ST, SL W }
v d n t(v d) // n t l z p rt p ns, t m r, rt nd dc
v d w t_ms( ns gn d nt)
v d l d( n m l d_st t )
nt b tt ry_l w(v d), b tt ry_f ll(v d)
v d sh td wn(v d) // t l st sh t d wn rt
nt m n() {
n t()
l d( N) // nd c t b tt r s r c nn ct d
w t_ms(1000)
wh l (!b tt ry_l w()) l d(b tt ry_f ll() ? N : F ST)
l d( FF)
sh td wn() //f rc s r t ch ng b tt r s
wh l (1)
}
Key scanning shall be running in background.
I need a timer interrupts at 1 milli-second interval, a uart with baud rate 9600, an adc with input connects to the 1.1 volt reference.
Toggle LED at 1 second
It is to verify timer setting and LED.
/* isr.c */
i u e a i e u
e u e a e O O O A A O };
oi ai u i e i }
oi e e u e a e }
i a e o oi e u ; }
i a e u oi e u 1; }
oi u o oi = U = = A A = ; }
oi i i oi
= ; 5 3 a ou u
= ; 1=
O = ; e e e i u i
A = ;
O A = 9; 1
U = 1 3; au =9
I = ; e a e I E O A
A U = 1 ; A e 1 1
A A = 7; A o e a a =1
= 3; e a a = u
U = E ; u o ua
ei ; e a e i e u
}
I I E O A e
a i i ou ;
i ou 999
ou = ;
I = 3 ;
}
}
# ncl d < vr/ nt rr pt.h>
n m l d_st t { N, FF, N RM L, F ST, SL W}
v d w t_ms( ns gn d nt t) {}
v d l d( n m l d_st t s) {}
nt b tt ry_l w(v d) { r t rn 0 }
nt b tt ry_f ll(v d) { r t rn }
v d sh td wn(v d) { TCCR0B CSR0B DDRB DCSR 0 }
v d n t(v d) {
DDRB 0x28 //PB , PB s tp t
DDRD 0x02 //PD TX
P RTD 0x0c //k y s ns p ns p ll h gh
TCCR0 2 //CTC
CR0 24 // ms
BRR0 0 //b d 600
T MSK0 2 // n bl T M R0 C MP
DM X 4 // r f, . V
DCSR 0x8 // DC n, pr sc l r 28
TCCR0B //pr sc l r 64, r n
CSR0B _BV(TX N0) //t rn n rt
s () // n bl nt rr pt
}
SR(T M R0_C MP _v ct) {
st t c nt c nt
f (++c nt > ) {
c nt 0
P NB _BV( )
}
}
Implementation of led()
/* led.c */
i u e a io
e u e a e O O O A A O };
a i e u e a e a e = O ;
a i i ou u a io ;
oi e e u e a e
i ;
a e = ;
i == O A = 1 ;
i == A = 5 ;
i == O = ;
I = O IE A ;
u a io = ;
I = O IE A ;
}
oi e oi
i a e == O O = 3 ; e u ; }
i a e == O O = 3 ; e u ; }
i ou u a io ou = ; I = 3 ; }
}
# ncl d < vr/ .h>
n m l d_st t { N, FF, N RM L, F ST, SL W }
st t c n m l d_st t st t FF
st t c nt c nt, d r t n
v d l d( n m l d_st t s) {
nt t
st t s
f (s N RM L) t 000
f (s F ST) t 00
f (s SL W) t 2000
T MSK0 & ~_BV( C 0 )
d r t n t
T MSK0 | _BV( C 0 )
}
v d _l d(v d) {
f (st t N) { P RTB | _BV( ) r t rn }
f (st t FF) { P RTB & ~_BV( ) r t rn }
f (++c nt > d r t n) { c nt 0 P NB _BV( ) }
}
void _led(void);
ISR(TIMER0_COMPA_vect) {
_led();
}
Implementation of wait(unsigned int)
/**/
a i u i e i i ;
u i e i e i oi
u i e i ;
I = O IE A ;
= i ;
I = O IE A ;
e u ;
}
oi ai u i e i
= e i ;
i e = e i ;
}
oi e oi ;
I I E O A e
i ;
e ;
}
st t c ns gn d nt t ck
ns gn d nt g tT ck(v d) {
ns gn d nt t
T MSK0 & ~_BV( C 0 )
t t ck
T MSK0 | _BV( C 0 )
r t rn t
}
v d w t_ms( ns gn d nt t) {
t + g tT ck()
wh l (t ! g tT ck())
}
v d _l d(v d)
SR(T M R0_C MP _v ct) {
++t ck
_l d()
}
Implementation of adc functions
/* adc.c */
i u e a io
a i i e u ;
a i i e e u oi
i ;
I = O IE A ;
= e u ;
I = O IE A ;
e u ;
}
i a e o oi e u e e u 51 ; } 7 o
i a e u oi e u e e u 9 ; } 7 7 o
oi a oi
e u = A ;
A A = A ;
}
# ncl d < vr/ .h>
st t c nt r s lt
st t c nt g tR s lt(v d) {
nt r
T MSK0 & ~_BV( C 0 )
r r s lt
T MSK0 | _BV( C 0 )
r t rn r
}
nt b tt ry_l w(v d) { r t rn g tR s lt() > 0 } //~ .4 v lts
nt b tt ry_f ll(v d) { r t rn g tR s lt() < 4 0 } //~ . v lts
v d _ dc(v d) {
r s lt DC
DCSR | _BV( DSC)
}
void _led(void), _adc(void);
ISR(TIMER0_COMPA_vect) {
++tick;
_led();
_adc();
}
Implementation of keypad scanning
/* key.c */
i u e a io
oi e oi
a i i ou ;
a i a e ;
a = ;
i ou 1 e u ;
ou = ;
= ;
i I = ;
i I 3 = 3 ;
= ;
= 1 ;
i I = 1 ;
i I 3 = ;
= 1 ;
= ;
i I = ;
i I 3 = 5 ;
= ;
i == e e u ;
e = ;
U = e ;
}
# ncl d < vr/ .h>
v d _k y(v d) {
st t c nt c nt
st t c ch r k y
ch r k 0
f (++c nt < 0) r t rn
c nt 0
DDRB | _BV(0)
f (!(P ND & _BV(2))) k | _BV(0)
f (!(P ND & _BV( ))) k | _BV( )
DDRB & ~_BV(0)
DDRB | _BV( )
f (!(P ND & _BV(2))) k | _BV( )
f (!(P ND & _BV( ))) k | _BV(4)
DDRB & ~_BV( )
DDRB | _BV(2)
f (!(P ND & _BV(2))) k | _BV(2)
f (!(P ND & _BV( ))) k | _BV( )
DDRB & ~_BV(2)
f (k k y) r t rn
k y k
DR0 0x40 | k y
}
void _led(void), _adc(void), _key(void);
ISR(TIMER0_COMPA_vect) {
++tick;
_led();
_adc();
_key();
}
Turn off compiler optimisation. _key() is timing critical.
留言
張貼留言