Offline
Newbie
Karma: 0
Posts: 10
|
 |
« on: May 27, 2012, 08:25:57 am » |
I've build a circuit based on DTMF decoder MT8870. A mobile phone is connected via headphone jack to MT8870. 4 outputs are then connected to 4 Arduino digital inputs as shown in schematic below.  int q_1 = 4; int q_2 = 5; int q_3 = 6; int q_4 = 7;
void setup() { Serial.begin(9600); pinMode(q_1, INPUT); pinMode(q_2, INPUT); pinMode(q_3, INPUT); pinMode(q_4, INPUT); }
void loop() { int q1 = digitalRead(q_1); int q2 = digitalRead(q_2); int q3 = digitalRead(q_3); int q4 = digitalRead(q_4); if (q1 == HIGH && q2 == LOW && q3 == LOW && q4 == LOW) { Serial.println("Input detected."); }
delay(1000); }
My problem: when I first power up DTMF circuit, arduino recognizes my if statement as true and serial answers with "Input detected.", evendo all 4 DTMF outputs are low. When MT8870 gets first dtmf signal (doesn't matter from which key), arduino starts working as it should - I only get "Input detected." if '1000' combination is active (key 1). If I turn the power off and then back on again, I'm stuck with the same problem again, until a key get pressed. Any ideas why? Are these outputs somehow floating after power on? And btw, grounds from arduino and my circuit are not connected, should they be? Because if I connect the grounds, keys 1, 2 and 3 from mobile aren't detected by MT8870. If I seperate the grounds, all keys work.
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 73
Posts: 6839
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #1 on: May 27, 2012, 08:53:25 am » |
Grounds have to be connected, if that causes another problem then that has to be looked into. Are these outputs somehow floating after power on? Unlikely, but try moving the delay to the top of the loop to give any such behaviour time to settle. When you get it working how will you detect the 0 code? It looks like you will have to read the StD signal. ______ Rob
|
|
|
|
« Last Edit: May 27, 2012, 08:56:12 am by Graynomad »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #2 on: May 27, 2012, 09:57:31 am » |
Hmm yeah, I also thought grounds have to be the same, but I can't seem to get the chip working OK if they are. And this only happens if I power my arduino via USB. If I use an external power adapter it's OK but then I can't test my program simultaneusly... So by using an external power supply I've got it to work as I wanted - with first key press I choose a device that I want to control and with second key press I turn it on or off. I want to simplify the code now, but I'm no expert in programming, so any tip would be aprecciated. Maybe to use an array for 4 input combination? Or maybe as byte comparisson somehow? int q_1 = 4; int q_2 = 5; int q_3 = 6; int q_4 = 7; int red = 8; // 1st device (red LED) int green = 9; // 2nd device (green LED) int std_out = 10;
void setup() { pinMode(q_1, INPUT); pinMode(q_2, INPUT); pinMode(q_3, INPUT); pinMode(q_4, INPUT); pinMode(std_out, INPUT); pinMode(red, OUTPUT); pinMode(green, OUTPUT); }
void loop() { // wait a bit... delay(500); // read inputs int q1 = digitalRead(q_1); int q2 = digitalRead(q_2); int q3 = digitalRead(q_3); int q4 = digitalRead(q_4); if (q1 == HIGH && q2 == LOW && q3 == LOW && q4 == LOW) // if 1st device detected with '1000' (key 1) { while (digitalRead(std_out) == LOW); // wait for next key press delay(100); q1 = digitalRead(q_1); // when next key press detected, read it q2 = digitalRead(q_2); q3 = digitalRead(q_3); q4 = digitalRead(q_4); if (q1 == HIGH && q2 == HIGH && q3 == LOW && q4 == HIGH) // if '1101' (key *) is pressed... { digitalWrite(red, HIGH); // turn on 1st device } else if (q1 == LOW && q2 == LOW && q3 == HIGH && q4 == HIGH) // if '0011' (key #) is pressed... { digitalWrite(red, LOW); // turn off 1st device } } else if (q1 == LOW && q2 == HIGH && q3 == LOW && q4 == LOW) // if 2nd device detected with '0100' (key 2) { while (digitalRead(std_out) == LOW); // wait for next key press delay(100); q1 = digitalRead(q_1); // when next key press detected, read it q2 = digitalRead(q_2); q3 = digitalRead(q_3); q4 = digitalRead(q_4); if (q1 == HIGH && q2 == HIGH && q3 == LOW && q4 == HIGH) // if '1101' (key *) is pressed... { digitalWrite(green, HIGH); // turn on 2nd device } else if (q1 == LOW && q2 == LOW && q3 == HIGH && q4 == HIGH) // if '0011' (key #) is pressed... { digitalWrite(green, LOW); // turn off 2nd device } }
}
|
|
|
|
« Last Edit: May 27, 2012, 10:57:05 am by wicket »
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6400
-
|
 |
« Reply #3 on: May 27, 2012, 12:10:13 pm » |
It sounds as if you've got an unexpected voltage difference between the Arduino and your DTMF decoder. Can you measure the difference between the two grounds when the system is wired up in the way that works? Can you measure the signal voltage on those four pins relative to Arduino ground? If the grounds are close and you are getting a positive voltage in the right sort of range, it should work. So presumably you aren't. So you need to see what's actually happening on those pins.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 0
Posts: 54
|
 |
« Reply #4 on: May 27, 2012, 01:57:02 pm » |
Someone may come up some better hints, but something along these lines should help cut the memory usage a lot. If you need any of it explained let me know. #define Q1 4 #define Q2 5 #define Q3 6 #define Q4 7 #define RED 8 // 1st device (RED LED) #define GREEN 9 // 2nd device (GREEN LED) #define std_out 10
void setup() { pinMode(Q1, INPUT); pinMode(Q2, INPUT); pinMode(Q3, INPUT); pinMode(Q4, INPUT); pinMode(std_out, INPUT); pinMode(RED, OUTPUT); pinMode(GREEN, OUTPUT); }
void loop() { byte key; // wait a bit... delay(500); // read inputs key = read_inputs(); if (key == B1000) // if 1st device detected with '1000' (key 1) { while (digitalRead(std_out) == LOW); // wait for next key press delay(100); key = read_inputs(); if (key == B1101) // if '1101' (key *) is pressed... { digitalWrite(RED, HIGH); // turn on 1st device } else if (key == B0011) // if '0011' (key #) is pressed... { digitalWrite(RED, LOW); // turn off 1st device } } else if (key == B0100) // if 2nd device detected with '0100' (key 2) { while (digitalRead(std_out) == LOW); // wait for next key press delay(100); key = read_inputs(); if (key == B1101) // if '1101' (key *) is pressed... { digitalWrite(GREEN, HIGH); // turn on 2nd device } else if (key == B0011) // if '0011' (key #) is pressed... { digitalWrite(GREEN, LOW); // turn off 2nd device } }
}
byte read_inputs(){ byte key = 0; if(digitalRead(Q1)) key &= 1; key <<= 1; if(digitalRead(Q2)) key &= 1; key <<= 1; if(digitalRead(Q3)) key &= 1; key <<= 1; if(digitalRead(Q4)) key &= 1; return key; }
|
|
|
|
|
Logged
|
|
|
|
|
Left Coast, CA (USA)
Offline
Brattain Member
Karma: 279
Posts: 15320
Measurement changes behavior
|
 |
« Reply #5 on: May 27, 2012, 01:58:10 pm » |
You should be wiring the valid data available to read signal ( StD )to an ardino input pin and only read the other four data pin values when StD goes high.
Lefty
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 73
Posts: 6839
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #6 on: May 27, 2012, 06:09:52 pm » |
Here's my refactored version int q_1 = 4; int q_2 = 5; int q_3 = 6; int q_4 = 7; int red = 8; // 1st device (red LED) int green = 9; // 2nd device (green LED) int std_out = 10;
void setup() { pinMode(q_1, INPUT); pinMode(q_2, INPUT); pinMode(q_3, INPUT); pinMode(q_4, INPUT); pinMode(std_out, INPUT); pinMode(red, OUTPUT); pinMode(green, OUTPUT); }
int getKey () { int keyVal = 0;
while (digitalRead(std_out) == HIGH); // wait for key to be released while (digitalRead(std_out) == LOW); // wait for next key press delay(10); // debounce if needed keyVal |= digitalRead(q_4) << 3; // depends on HIGH always being defined as 1 keyVal |= digitalRead(q_3) << 2; keyVal |= digitalRead(q_2) << 1; keyVal |= digitalRead(q_1); return keyVal; }
void loop() { int keyVal = 0; // wait a bit... delay(500); keyVal = getKey();
switch (keyVal) { case B1000: keyVal = getKey(); switch (keyVal) { case B1101: digitalWrite(red, HIGH); // turn on 1st device break; case B0011: digitalWrite(red, LOW); // turn off 1st device break; }
case B0100: keyVal = getKey(); switch (keyVal) { case B1101: digitalWrite(green, HIGH); // turn on 1st device break; case B0011: digitalWrite(green, LOW); // turn off 1st device break; } } } You could also accumulate the two key values and combine them to make a single case statement, if you had more options I would be inclined to do that. ______ Rob
|
|
|
|
« Last Edit: May 27, 2012, 09:58:04 pm by Graynomad »
|
Logged
|
|
|
|
|
Offline
Sr. Member
Karma: 0
Posts: 275
|
 |
« Reply #7 on: May 27, 2012, 09:46:40 pm » |
I have to say I was a little disappointed when I read the description of the problem after reading the title.
I was hoping someone was using the Arduino to decode DTMF tones. Maybe some routine using FFT or something.
It looks like you should be getting good reads from you decoder chip now.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #8 on: May 28, 2012, 04:19:11 am » |
It sounds as if you've got an unexpected voltage difference between the Arduino and your DTMF decoder. Can you measure the difference between the two grounds when the system is wired up in the way that works? Can you measure the signal voltage on those four pins relative to Arduino ground? If the grounds are close and you are getting a positive voltage in the right sort of range, it should work. So presumably you aren't. So you need to see what's actually happening on those pins.
I'm powering my arduino via USB and my circuit from external 5V (230V) supply. Ground difference is 0,36V. If I join grounds only, half of the keys stop working. If I join grounds and external 5V + arduino 5V it starts working again. Does this make sense? Does is maybe have to do something with laptop power supplies and/or some 230V installation having GND an N joined together? @iggykoopa & @Graynomad: Yeah, that's what I had in mind. I understand the code, but for some reason it's not working. It's doesn't enter any case statement. I've played with both codes for a bit, but didn't get it to work.  I mean it's not a huge problem if I don't use a tweaked code, but as you said, it would help me if I start adding more devices. Thanks anyway, I'll try some more minor changes and see if it starts working. @RandallR: Yeah sorry, could've picked a better suited title. Although I'm also interested in how to decode DTMF tones with Arduino... 
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Tesla Member
Karma: 89
Posts: 6400
-
|
 |
« Reply #9 on: May 28, 2012, 08:36:13 am » |
I'm powering my arduino via USB and my circuit from external 5V (230V) supply. Ground difference is 0,36V. If I join grounds only, half of the keys stop working. If I join grounds and external 5V + arduino 5V it starts working again. Does this make sense? Does is maybe have to do something with laptop power supplies and/or some 230V installation having GND an N joined together?
Having ground and 5V rails connected doesn't sound right - you'll end up with the two regulators fighting each other. Can you measure the DC voltage from the signal line to ground on your DTMF detectors and the same on the Arduino when you have the grounds connected? It may be that those fractions of a volt difference are enough to take your signal below the threshold that the digital input will detect.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Faraday Member
Karma: 6
Posts: 2504
|
 |
« Reply #10 on: June 10, 2012, 08:00:02 am » |
Read the datasheet - your circuit is broken. In particular, INH and POWERDOWN (pins 5 and 6) should be tied to ground. I'm also not convinced the 5k resistor on the ground side of the input is needed - it may result in too much attenuation. a 0.1uF for C2 should be sufficient for headphone/speaker level audio sources. How large are the LED resistors? Check the datasheet to make sure the 8870 Qn outputs have enough drive, or just disconnect them temporarily.  Here's a sketch for the circuit above (may have Q1-Q4 mirrored): http://www.eng.uah.edu/~jdw/avr/servo_dtmf_cutdown.pde Note this sketch uses direct PORT manipulation and uses interrupts. -j
|
|
|
|
|
Logged
|
|
|
|
|
|