Hallo zusammen, ich möchte gerne ein GSM-Modem ansteuern. Sprich ein anderes Modem anrufen. Wenn nach einer bestimmten Zeit das Modem nicht antwortet will ich eine andere Nummer wählen. ATD+xxxxxxxx; bspw. 10 sek warten! Wenn keine Antwort, neue Nummer wählen! Ich verwende eine Arduino Mega Board: ATmega2560 mit 16MHz. Counter und Timer bereiten mir noch etwas Kopfzerbrechen und ich steig nicht so richtig durch und weiß nicht so richtig, wie ich das angehen soll. Muss man das mit Interrupts machen? Gruß Michel
Hallo, Danke für die Antwort. Wie reagiere dann aber, wenn eine Antwort kommt?
@ Michel (Gast)
>Danke für die Antwort. Wie reagiere dann aber, wenn eine Antwort kommt?
Indem man eben NICHT 10x 1000ms wartet, sondern eher 10.000 mal 1ms.
Etwa so.
1 | for( int i = 0; i<10000; i++) { |
2 | _delay_ms(1); |
3 | if(UART_RXC) { |
4 | // Antwort, weiter gehts
|
5 | break; |
6 | }
|
7 | }
|
Siehe Multitasking MfG Falk
Hi! Also wenn du einen Timer starten willst, hab ich hier mal was für dich:
1 | #include <avr/interrupt.h> |
2 | //#include <avr/math.h>
|
3 | |
4 | |
5 | #define MCU_FREQ 16000000
|
6 | #define SAMPLINGRATEHZ 300
|
7 | #define PRESCALER 8
|
8 | //1 Tick = 16e6 / 8 Prescaler => 2.000.000 Ticks pro Sekunde => 2.000.000/HERTZ = TimerTicks
|
9 | //(entspricht bei 300Hz 6666 Ticks = 0x1A0B) => Timer Offset muss auf 0xFFFF-0x1A0B gestellt werden
|
10 | // damit alle 0x1A0B Ticks ein Overflow entsteht
|
11 | |
12 | int timer1Offset = 0xFFFF - (MCU_FREQ/(PRESCALER*SAMPLINGRATEHZ)); |
13 | |
14 | void setup() |
15 | {
|
16 | //Configure Timer 1
|
17 | PRR &= ~(1<<PRTIM1); //disable Power Reduction Timer 1 (PRTIM1); |
18 | TCCR1A = 0x00; //Normal Mode |
19 | TCNT1 = timer1Offset; //Setz den Timer auf den Startwert. |
20 | |
21 | |
22 | if (1== PRESCALER) TCCR1B = 0b0000001; //Normal mode with prescaler 1 |
23 | if (8== PRESCALER) TCCR1B = 0b0000010; //Normal mode with prescaler 8 |
24 | if (64== PRESCALER) TCCR1B = 0b0000011; //Normal mode with prescaler 64 |
25 | if (256== PRESCALER) TCCR1B = 0b0000100; //Normal mode with prescaler 256 |
26 | if (1024== PRESCALER) TCCR1B = 0b0000101; //Normal mode with prescaler 1024 |
27 | |
28 | TIMSK1 |= (1<<0); //Enable Overflow Interrupt |
29 | sei(); //set_interrupts(), nicht sicher, ob man das auch noch braucht |
30 | |
31 | }
|
32 | |
33 | |
34 | //diese Funktion wird aufgerufen, wenn der Timer überlauft (TCNT1 == 0xFFFF)
|
35 | ISR (TIMER1_OVF_vect) |
36 | {
|
37 | // ändere die wählnummer hier
|
38 | |
39 | //reset des Timers auf den Startwert
|
40 | TCNT1 = timer1Offset; |
41 | }
|
In diesem Beispiel wird der Timeroverflow 300 mal/sekunde aufgerufen. Um auf einmal in 10 Sek. zu kommen müsstest du dein timer1Offset so berechnen: 0xFFFF - ((MCU_FREQ/PRESCALER) * 10), was aber nicht geht weil selbst bei Prescaler 1024 kommst du beim Klammernterm auf 156250, was keine 16bit Zahl mehr ist! Daher kannst du nur zb. 0xFFFF - ((MCU_FREQ/PRESCALER) * 2) ausrechnen, also bei 1024 Prescaler 0xFFFF - 0x7A12 = 0x85ED. Dann wird die Interruptroutine alle 2 Sekunden aufgerufen. Die musst du dann so ändern, dass der Code nur jedes 5te mal ausgeführt wird:
1 | int i = 0; |
2 | ISR (TIMER1_OVF_vect) |
3 | {
|
4 | i++; |
5 | if (i>5) |
6 | {
|
7 | // ändere die wählnummer hier
|
8 | i=0; |
9 | }
|
10 | |
11 | //reset des Timers auf den Startwert
|
12 | TCNT1 = timer1Offset; |
13 | }
|
Ich hoffe das war verständlich und v.a. dass ich mich nicht verrechnet hab. Bitte zu bedenken, dass ich selbst auch noch Anfänger bin es geht sicher noch besser/schöner, aber so sollte es funktionern. Viel Glück!
achja, wenn eine Antwort kommt sowohl TCNT1 = timer1Offset setzen als auch i=0;
Hallo,
vielen Dank für die Antworten. Ich habs nun mal probiert, aber es klappt
noch nicht so richtig. Also im Grunde will ich eine Nummer anrufen und
wenn die/der nach 15 Sekunden ran geht, die Verbindung beenden und eine
andere Nummer wählen.
Ich hab also zwei Nummern, die abwechselnd anrufen will, bis jemand ran
geht, bzw. durch Auflegen bemerkbar macht, dass er da ist. Ich erhalte
dann vom Modem die Antwort BUSY. Mit gsm_ans = 1 springe ich in
gsm_antwort()und warte/werte die Antwort des Modems ab/aus. Wenn nicht
BUSY detektiert wurde soll der Anruf nach 15 min mit ATH beendet und das
Ganze von vorne beginnen. Wenn das Modem nach ATD+xxxxx; sendet erhöhe
ich init_step um eins.
Ich habs nun mal mit einer Nummer versucht und es klappt nicht
richtig...Ich seh den Fehler nicht...zum Haare raufen!
Es wäre wirklich nett wenn mir jemand weiterhelfen könnte. VG
do
if ( gsm_ans == 0 )
{
if ( init_step == 0 )
{
uarts( "ATD" );
uarts( number1 );
uarts( ";" );
gsm_ans = 1;
}
if ( init_step == 1 )
{
for( int i = 0; i<15000; i++)
{
_delay_ms(1);
if( busy == 1 )
{
break;
}
}
if( busy == 1 )
{
uarts("BUSY detektiert");
busy = 0;
}
else
{
uarts( "ATH" );
init_step = 0;
}
gsm_ans = 1;
}
}
else
gsm_antwort();
while( init_step <= 1 );
Hallo glop! Mir scheint als würde das Programm gar nicht aus der Schleife bei busy == 1 springen. Ich hab nun auch einmal noch gsm_answer = 1 in die Schleife gepackt, ohne Erfolg.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.