Forum: Projekte & Code ModelServo-Signal-Serialisierer Mega8


von Jasson J. (jasson)


Lesenswert?

Hab heute ein für ein sehr uniques Vorhaben eine Kleinigkeit gemacht -


Hatte ursprünglich gar nicht vor, das zu Posten, aber ich im Laufe über 
zwei kleine Kopfnüsse gestolpert, die ich doch ganz nett fand.

Ich brauchte für ein Vorhaben etwas, das aus 4 Signalen für 
Modellbauservos ein serielles - das PPM Signal macht.
Damit es nicht zu einfach wird spuckt die Signalquelle die natürlich 
NICHT zeitlich versetzt an ihren Pins aus, sondern mit einem 
gleichzeitigen Start. Sonst hätte man es vielleicht einfach mit etwas 
Diodenlogik lösen können.

Da ich jetzt nicht für jedes Problem mit BluePills um mich feuern will 
weil die so schön viele Timer und CC-Register hat, hab ich es auf einem 
Mega8 gemacht, der noch da ist.

>>Mh... okay 4 parallele Signale sampeln, die nicht mega weit von der 
Systemgeschwindigkeit weg sind. Na gut - wenn´s schee macht...


Am Ende ist es auf ein abgewandeltes Konzept hinaus gelaufen, wie ich es 
auf einem Tiny gemacht habe. .

Hilfreich ist, dass das Einlesen der 4 parallelen Eingangssignale und 
das anschließend serielle ausgeben, aus PPM Sicht die Dauer von 5 
Kanälen hat, was in das 20ms Fenster passt.
So entstand die Idee den Tiny-Ansatz zu übernehmen, die gesamte Sache 
stumpf und ausschließlich  in der Mainloop laufen zu lassen und den 
Start der Einganssignalperiode als Startschuss für die 
Sample-Generate-Loop zu nehmen.
Der Schuss ist, wenn alle Eingangssignale high sind. Gleich kommt was zu 
der impliziten Flankenerkennung.
Die Eingangssignale hängen alle an PORTC0:3 und werden einfach durch 
Einlesen von PORTC & 15 gemacht. Als ich so am rumdebuggen war, hab ich 
die Anzahl der gesampelten Kanäle bis 1 verringert und beim späteren 
erhöhen übersehen, dass PORTC0:3 bitstuffed ist und eine Erhöhung von 1 
auf 2 nicht der Hinzunahme eines weiteren Kanals entspricht. So kamen 
auf dem Oszi originelle Flankenmuster raus.
Sind alle Signale high, werden sie in einer While-Loop gesampelt, bis 
alle wieder Low sind. -> Hier ist die Flankenerkennung :)
> Hier war die zweite Kopfnuss fällig.
Natürlich brauchen alle Eingangssignale ein Flag, ob sie schon zu Ende 
gesamplet wurden. Sonst werden sie ja laufend überschrieben.
Hatte ich natürlich zu erst nicht dran gedacht, sah auf dem Oszi im 
Ausgangssignal nur so aus, als ob alle Eingangssignale "irgendwie 
komisch" zusammenhängen.

Die Outputerzeugung läuft im Spaghetti-Style in 4 Blöcken + 
Abschluss"höcker" ab. Hab versucht aus zu baldovern, ob sich einer der 
PWM Modi eignet. Aber ich war mir ohne längerwieriges Einlesen in die 
genauen Details der Modi nicht ausreichend sicher.
Das nicht ausreichend sicher in begrenzter Zeit raus zu kriegen und dem 
Gefühl der Restunsicherheit und das sich diese eventuellen Effekte mit 
anderen Bugs mischen hat mich zur aktuellen Spaghetti-Lösung kommen 
lassen.

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdint.h>
4
5
volatile unsigned int pulseArr[4] = {1000, 1300, 1600, 2000};
6
7
int main(void)
8
{ 
9
unsigned int tickCntr = 0;
10
char tmpPin, allDoneFlags = 15;
11
DDRB = 2;
12
TCCR1B = 0b00000010;
13
while(1)
14
{
15
/*  */
16
  
17
  PORTB = 0;
18
  pulseArr[0] = 0; 
19
  pulseArr[1] = 0; 
20
  pulseArr[2] = 0; 
21
  pulseArr[3] = 0; 
22
23
  while(1)//wait for all Pins to be high
24
  {
25
    tmpPin = PINC & 2;
26
    if(tmpPin == 2)break; //then all Pins are high  
27
  }
28
29
  TCNT1 = 0;
30
  while(TCNT1 < 100)//avoid possible flickers
31
  {
32
  }
33
34
  allDoneFlags = 15;
35
  while(allDoneFlags != 0)//runs as long until all Pins are low again
36
  {
37
    tmpPin = PINC & 15;
38
    allDoneFlags &= tmpPin;
39
40
    //The "(pulseArr['n'] == 0)" checks are used as a flag that the certain channel is measured
41
    // Otherwise it gets permanently overwritten 
42
    if(((tmpPin & 1) == 0) && (pulseArr[0] == 0))pulseArr[0] = TCNT1;
43
    if(((tmpPin & 2) == 0) && (pulseArr[1] == 0))pulseArr[1] = TCNT1;
44
    if(((tmpPin & 4) == 0) && (pulseArr[2] == 0))pulseArr[2] = TCNT1;
45
    if(((tmpPin & 8) == 0) && (pulseArr[3] == 0))pulseArr[3] = TCNT1;
46
    // Pssst... (honestly here is (at least technically) some jitter going on)
47
  }
48
49
  // subtract the 1ms offset from the 1.5 ms signal
50
  if(pulseArr[0] < 1000)pulseArr[0] = 0;
51
  else pulseArr[0] -= 1000;
52
53
  if(pulseArr[1] < 1000)pulseArr[1] = 0;
54
  else pulseArr[1] -= 1000;
55
56
  if(pulseArr[2] < 1000)pulseArr[2] = 0;
57
  else pulseArr[2] -= 1000;
58
59
  if(pulseArr[3] < 1000)pulseArr[3] = 0;
60
  else pulseArr[3] -= 1000;
61
62
  //do the pulses of the 4 channels after another
63
  PORTB = 2;
64
  TCNT1 = 0;  
65
  OCR1A = 400;
66
  TIFR |= 0b00010000;
67
  while(!(TIFR & 0b00010000));
68
  PORTB = 0;
69
  TCNT1 = 0;  
70
  OCR1A = pulseArr[0]+600;
71
  TIFR |= 0b00010000;
72
  while(!(TIFR & 0b00010000));
73
74
  PORTB = 2;
75
  TCNT1 = 0;  
76
  OCR1A = 400;
77
  TIFR |= 0b00010000;
78
  while(!(TIFR & 0b00010000));
79
  PORTB = 0;
80
  TCNT1 = 0;  
81
  OCR1A = pulseArr[1]+600;
82
  TIFR |= 0b00010000;
83
  while(!(TIFR & 0b00010000));
84
85
  PORTB = 2;
86
  TCNT1 = 0;  
87
  OCR1A = 400;
88
  TIFR |= 0b00010000;
89
  while(!(TIFR & 0b00010000));
90
  PORTB = 0;
91
  TCNT1 = 0;  
92
  OCR1A = pulseArr[2]+600;
93
  TIFR |= 0b00010000;
94
  while(!(TIFR & 0b00010000));
95
96
  PORTB = 2;
97
  TCNT1 = 0;  
98
  OCR1A = 400;
99
  TIFR |= 0b00010000;
100
  while(!(TIFR & 0b00010000));
101
  PORTB = 0;
102
  TCNT1 = 0;  
103
  OCR1A = pulseArr[3]+600;
104
  TIFR |= 0b00010000;
105
  while(!(TIFR & 0b00010000));
106
107
  // "Stop token"
108
  PORTB = 2;
109
  TCNT1 = 0;  
110
  OCR1A = 400;
111
  TIFR |= 0b00010000;
112
  while(!(TIFR & 0b00010000));
113
  PORTB = 0;
114
}  
115
}

: Bearbeitet durch User
von Jasson J. (jasson)


Lesenswert?

>> Ach ja - es darf gerne konstruktiv gemeckert werden oder eigene Ideen kund 
getan werden, wenn vorhanden - bin neugierig.

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
Noch kein Account? Hier anmelden.