Forum: Compiler & IDEs C-Code für Fahrtregler anpassen


von Andre Meschke (Gast)


Lesenswert?

Hallo,
ich habe hier einen Code für einen RC Fahrtregler auf Atmega8 Basis.
Der Regler funktioniert auch gut bis auf eine Kleinigkeit die jedoch 
sehr stört.
Und zwar egal ob vorwärts oder rückwärts nach ca 75% des 
Knüppelausschlages an der Fernbedienung wenn der Motor auch mit 75% 
seiner Leistung dreht kommt es zu einem Sprung auf 100%. Mir fehlt also 
proportionaler Stellweg.
An welcher Stelle muss ich den Code abändern damit das passt?
1
/* Brushed project
2
Main code file. 
3
 */
4
5
//Set your controller here
6
#include "../pindefs/tz85a.h"
7
8
9
#include <avr/io.h>
10
#include <avr/pgmspace.h>
11
#include <stdint.h>
12
#include <util/delay.h>
13
#include <avr/interrupt.h>
14
#include <math.h>
15
#include <avr/eeprom.h>
16
17
//Define RC States
18
#define unitialised  0
19
#define forward  1
20
#define backward  2
21
#define brake  3
22
23
//Define Temp States
24
#define HOT  2
25
#define WARM 1
26
#define COOL 0
27
28
volatile uint8_t state = 0;
29
volatile uint16_t prevTime = 0;
30
volatile uint16_t rcTime = 0;
31
volatile uint8_t time0 = 0;
32
volatile uint8_t failsafe = 0;
33
volatile uint8_t timeout = 50;
34
volatile uint8_t newState = 0;
35
volatile uint8_t lets_get_high = 0;
36
volatile uint8_t tempState = 0;
37
volatile uint8_t rcTick = 0;
38
volatile uint8_t desiredPWM = 0;
39
40
//Stored data variables
41
volatile uint16_t rcLow = RC_LOW;
42
volatile uint16_t rcHigh = RC_HIGH;
43
volatile uint16_t rcMid = (RC_LOW + RC_HIGH) / 2;
44
volatile uint8_t maxSlew = MAX_SLEW;
45
volatile uint8_t tempLimit = TEMP_LIMIT;
46
volatile uint8_t goExpo = EXPO;
47
48
//Define memory states
49
uint16_t EEMEM storedRcLow = RC_LOW;
50
uint16_t EEMEM storedRcHigh = RC_HIGH;
51
uint8_t EEMEM storedSlewRate = MAX_SLEW;
52
uint8_t EEMEM storedExpo = EXPO;
53
uint8_t EEMEM storedTempLimit = TEMP_LIMIT;
54
55
//Setup 2 ports which we are using for H bridge. e.g.
56
/* Forward = B High, A Low
57
58
   Reverse = B Low,  A High
59
 */
60
61
#define FORWARD_LOW  LOW_A
62
#define FORWARD_LOW_PORT   LOW_A_PORT
63
64
#define FORWARD_HIGH HIGH_B
65
#define FORWARD_HIGH_PORT  HIGH_B_PORT
66
67
#define BACKWARD_LOW  LOW_B
68
#define BACKWARD_LOW_PORT  LOW_B_PORT
69
70
#define BACKWARD_HIGH HIGH_A
71
#define BACKWARD_HIGH_PORT HIGH_A_PORT
72
73
inline void setForwardLow();
74
inline void clrForwardLow();
75
inline void setForwardHigh();
76
inline void clrForwardHigh();
77
78
inline void setBackwardLow();
79
inline void clrBackwardLow();
80
inline void setBackwardHigh();
81
inline void clrBackwardHigh();
82
83
//Motor State Functions
84
void goForwards();
85
void braking();
86
void goBackwards();
87
88
//Programming functions
89
void motorBeep(uint8_t length);
90
void fastBeep(uint8_t length);
91
void waitForState(uint8_t waitForState);
92
void readData();
93
void calibrateRC();
94
void setSlewRate();
95
void setExpo();
96
void setTempLimit();
97
98
int main() {
99
    //Initialisation
100
101
    //Setup Outputs
102
    _delay_ms(10);
103
104
    clrBackwardLow();
105
    clrBackwardHigh();
106
    clrForwardLow();
107
    clrForwardHigh();
108
109
    SET_HIGH_A_PORT |= (1 << HIGH_A);
110
    SET_HIGH_B_PORT |= (1 << HIGH_B);
111
    SET_HIGH_C_PORT |= (1 << HIGH_C);
112
113
    SET_LOW_A_PORT |= (1 << LOW_A);
114
    SET_LOW_B_PORT |= (1 << LOW_B);
115
    SET_LOW_C_PORT |= (1 << LOW_C);
116
117
    //setForwardLow();
118
    
119
120
    //_delay_ms(100);
121
122
    //Setup Timer
123
    TCCR0 = 0b00000011; //Setup Timer 0 - scaling or (go check the datasheet and fill it in)
124
    TIMSK = (1 << TOIE0) | (1 << OCIE2) | (1 << TOIE2); //Enable Timer0 Overflow interrupt, Timer2 Output Compare and Timer2 Overflow interrupt
125
126
    //Setup PWM Timer
127
    OCR2 = 0x00; //Set the compare value to 0 or off
128
    TCCR2 = (1 << CS21); //Set the timer 2 scaling of (go check the datasheet and fill it in)
129
130
    //Enable RC Interrupt
131
    MCUCR |= (1 << ISC00); //Set INT0 to trigger on both edges
132
    GICR |= (1 << INT0); //Enable INT0
133
134
    newState = unitialised;
135
    braking();
136
137
    _delay_ms(100);
138
139
140
141
    //Setup ADC
142
#ifdef TEMP_ADMUX
143
  if (tempLimit){
144
      ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescaler to 128 - 125KHz sample rate @ 16MHz
145
146
      ADMUX |= (1 << REFS0); // Set ADC reference to AVCC
147
      ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading
148
149
      ADMUX |= TEMP_ADMUX; //Set ADC to temp sensor
150
151
      ADCSRA |= (1 << ADFR); // Set ADC to Free-Running Mode
152
      ADCSRA |= (1 << ADEN); // Enable ADC
153
      ADCSRA |= (1 << ADIE); // Enable ADC Interrupt
154
      ADCSRA |= (1 << ADSC); // Start A2D Conversions
155
  }
156
#endif
157
158
    //while(1){
159
    //setForwardHigh();
160
    //_delay_ms(1);
161
    //clrForwardHigh();
162
    //}
163
164
    sei();
165
    //End initialisation 
166
167
    //Calibration loop
168
    uint8_t timeout = 0;
169
    uint8_t calibrating = CALIBRATION;
170
    while (calibrating) {
171
        //If we are getting RC pusles
172
        if (failsafe > 10) {
173
            //if we are getting a pulse see if its up the top.
174
            if (newState == forward && desiredPWM > 100) {
175
                //Wait for 2s and see if it stays high
176
                timeout = 0;
177
                while (newState == forward && desiredPWM > 100 && timeout < 199) {
178
                    _delay_ms(20);
179
                    timeout++;
180
                }
181
182
                //Check if its stayed high 
183
                if (timeout > 190) {
184
185
                    //Yay we are in programming mode
186
                    calibrateRC();
187
                    _delay_ms(2000);
188
                    setSlewRate();
189
                    _delay_ms(2000);
190
                    setExpo();
191
                    _delay_ms(2000);
192
                    setTempLimit();
193
                    _delay_ms(2000);
194
                    while (newState != brake) {
195
                        fastBeep(4);
196
                    }
197
                }
198
                calibrating = 0;
199
            } else {
200
                calibrating = 0;
201
            }
202
        }
203
204
        //If not wait and beep for 20s
205
        _delay_ms(500);
206
        timeout++;
207
        if (timeout > 19) {
208
            calibrating = 0;
209
        }
210
        if (timeout % 2) {
211
            motorBeep(1);
212
        }
213
    }
214
215
    //readData();
216
217
    timeout = 0;
218
    //waitForState(brake);
219
220
    motorBeep(3);
221
    
222
223
    //Main loop
224
    //Here we manage what mode we are in everything else is done in interrupts
225
    while (1) {
226
        //RC Tick runs @ approximately 1kHz on @ 16Mhz or 500hz @ 8Mhz        
227
        if (rcTick) {
228
            //Manage State
229
             
230
            
231
            if (state != newState) {
232
            
233
                //If we are in the brake state then we can go in either direction
234
                //if (state == brake){
235
236
                if (newState == forward && state == brake) {
237
                    OCR2 = 0;
238
                    goForwards();
239
                } else if (newState == backward && state == brake) {
240
                    OCR2 = 0;
241
                    goBackwards();
242
                } else {
243
                    //If we have ramped down then go to braking mode
244
                    if (OCR2 <= 10) {
245
                        braking();
246
                        OCR2 = 255;
247
                    }                        //Other wise we want to change our state so first we need to ramp down, then we can change state.
248
                    else {
249
                        OCR2 = OCR2 - maxSlew;
250
                    }
251
                }
252
            }                //Manage slew rate
253
            else if (OCR2 != desiredPWM) {
254
                if (desiredPWM > (OCR2 + maxSlew)) {
255
                    OCR2 = OCR2 + maxSlew;
256
                } else if (desiredPWM < (OCR2 - maxSlew)) {
257
                    OCR2 = OCR2 - maxSlew;
258
                } else {
259
                    OCR2 = desiredPWM;
260
                } 
261
            }
262
            rcTick = 0; 
263
        }
264
    }
265
}
266
267
268
//This interrupt manages failsafe and time0 for upper half of RC timer (lower half is TCNT0)
269
270
ISR(TIMER0_OVF_vect) {
271
    //Check failsafe
272
273
    if (timeout == 0) { //If we are out of counts go to braking mode
274
        newState = brake;
275
    } else {
276
        timeout--; //otherwise decrease failsafe counter
277
    }
278
    time0++; //time0 is upper bit for RC timer. 
279
    rcTick++;
280
}
281
282
//This interrupt manages RC pulses
283
284
ISR(INT0_vect) {
285
    //Read in the current time
286
    uint16_t time = TCNT0; //Read lower
287
    time = time + time0 * 256; //Add upper
288
    //Read in current time
289
    if (RC_PORT & (1 << RC_PIN)) { //If the pin is high (then its just switched on)
290
        prevTime = time; //then save the current time
291
    } else {
292
        uint16_t time_diff = time - prevTime;
293
        rcTime = time_diff;
294
        //Update PWM and direction
295
        uint8_t deadzone = DEADTIME;
296
        uint8_t buffer = BUFFERTIME;
297
        uint8_t maxOut = MAXOUTTIME;
298
299
 
300
301
        if (((time_diff > (rcLow - buffer)) && (time_diff < (rcHigh + buffer))) && (tempState != HOT)) { //Check for valid pulse
302
            if (failsafe > 10) { //Need 10 good pulses before we start
303
                failsafe = 15; //Set valid pulse counter (15-10 = 5) therfore we can receive 5 bad pulses before we stop
304
                timeout = 50; //Set timeout counter
305
306
                //Vaild signal
307
       
308
                if (time_diff > (rcMid - deadzone) && time_diff < (rcMid + deadzone)) { //If center brake
309
                    desiredPWM = 255;
310
                    newState = brake;
311
312
                } else if (time_diff < rcMid) { //If low then go backwards
313
314
                    if (time_diff < (rcLow + maxOut)) {
315
                        desiredPWM = 255;
316
                    } else {
317
                        desiredPWM = (rcMid - deadzone - time_diff)*256 / (rcMid - deadzone - rcLow);
318
                        if (EXPO) {
319
                            desiredPWM = (uint16_t) desiredPWM * desiredPWM / 256;
320
                        }
321
                    }
322
                    newState = backward;
323
324
          if(tempLimit){
325
                      if (tempState == WARM && OCR2 > 128) {
326
                          desiredPWM = 128;
327
                      }
328
          }
329
330
                } else { //Else go forward
331
                    if (time_diff > (rcHigh - maxOut)) {
332
                        desiredPWM = 255;
333
                    } else {
334
                        desiredPWM = (time_diff - rcMid - deadzone)*256 / (rcHigh - rcMid - deadzone);
335
                        if (EXPO) {
336
                            desiredPWM = (uint16_t) desiredPWM * desiredPWM / 256;
337
                        }
338
                    }
339
                    newState = forward;
340
341
          if(tempLimit){
342
                    if (tempState == WARM && OCR2 > 128) {
343
                        desiredPWM = 128;
344
                    }
345
          }
346
347
                }
348
            } else {
349
                failsafe++; //If havent got 10 valid pulses yet increase count and keep waiting
350
            }
351
        } else { //If there is an invalid pulse
352
            //Failsafe
353
            failsafe--; //decrease counter
354
            if (failsafe < 10) { //If we have had enough invalid pulses
355
                newState = brake; //go to failsafe breaking mode
356
            }
357
        }
358
    }
359
}
360
361
ISR(TIMER2_COMP_vect) { //When comparator is triggered clear low ports (off part of PWM cycle)
362
    if (OCR2 < 255) {
363
        if (state != brake) {
364
            //Clear high
365
            clrForwardHigh();
366
            clrBackwardHigh();
367
        }
368
    }
369
}
370
371
ISR(TIMER2_OVF_vect) { //When timer overflows enable low port for current state
372
    if (OCR2 > 0) {
373
        if (state == forward) {
374
            setForwardHigh();
375
        } else if (state == backward) {
376
            setBackwardHigh();
377
        }
378
    }
379
    if (OCR2 > 250 && state != brake) {
380
        lets_get_high++; //Gotta keep the charge pump circuit charged
381
        if (lets_get_high > 50) { //If it hasn't had a chance to charge in a while
382
            clrForwardHigh(); //Clear it then reset counter   
383
            clrBackwardHigh(); //Now pumped up and remaining high so we don't nasty shoot through which ends in magic smoke :)
384
            lets_get_high = 0;
385
        }
386
    }
387
}
388
389
#ifdef TEMP_ADMUX
390
ISR(ADC_vect) {
391
    if (ADCH < I_AM_HOT) {
392
        tempState = HOT;
393
        newState = brake;
394
    } else if (ADCH < I_AM_WARM) {
395
        tempState = WARM;
396
    } else {
397
        tempState = COOL;
398
    }
399
}
400
#endif
401
402
inline void setForwardLow() {
403
    if (LOW_ACTIVE_LOW) {
404
        FORWARD_LOW_PORT &= ~(1 << FORWARD_LOW);
405
    } else {
406
        FORWARD_LOW_PORT |= (1 << FORWARD_LOW);
407
    }
408
}
409
410
inline void clrForwardLow() {
411
    if (LOW_ACTIVE_LOW) {
412
        FORWARD_LOW_PORT |= (1 << FORWARD_LOW);
413
    } else {
414
        FORWARD_LOW_PORT &= ~(1 << FORWARD_LOW);
415
    }
416
}
417
418
inline void setForwardHigh() {
419
    if (HIGH_ACTIVE_LOW) {
420
        FORWARD_HIGH_PORT &= ~(1 << FORWARD_HIGH);
421
    } else {
422
        FORWARD_HIGH_PORT |= (1 << FORWARD_HIGH);
423
    }
424
}
425
426
inline void clrForwardHigh() {
427
    if (HIGH_ACTIVE_LOW) {
428
        FORWARD_HIGH_PORT |= (1 << FORWARD_HIGH);
429
    } else {
430
        FORWARD_HIGH_PORT &= ~(1 << FORWARD_HIGH);
431
    }
432
}
433
434
inline void setBackwardLow() {
435
    if (LOW_ACTIVE_LOW) {
436
        BACKWARD_LOW_PORT &= ~(1 << BACKWARD_LOW);
437
    } else {
438
        BACKWARD_LOW_PORT |= (1 << BACKWARD_LOW);
439
    }
440
}
441
442
inline void clrBackwardLow() {
443
    if (LOW_ACTIVE_LOW) {
444
        BACKWARD_LOW_PORT |= (1 << BACKWARD_LOW);
445
    } else {
446
        BACKWARD_LOW_PORT &= ~(1 << BACKWARD_LOW);
447
    }
448
}
449
450
inline void setBackwardHigh() {
451
    if (HIGH_ACTIVE_LOW) {
452
        BACKWARD_HIGH_PORT &= ~(1 << BACKWARD_HIGH);
453
    } else {
454
        BACKWARD_HIGH_PORT |= (1 << BACKWARD_HIGH);
455
    }
456
}
457
458
inline void clrBackwardHigh() {
459
    if (HIGH_ACTIVE_LOW) {
460
        BACKWARD_HIGH_PORT |= (1 << BACKWARD_HIGH);
461
    } else {
462
        BACKWARD_HIGH_PORT &= ~(1 << BACKWARD_HIGH);
463
    }
464
}
465
466
//Motor State Functions
467
468
void goForwards() {
469
    if (state != forward) {
470
        cli();
471
472
        //Clear unused pins
473
        clrBackwardHigh();
474
        clrBackwardLow();
475
        _delay_us(200); //Fet switch delay
476
        setForwardLow();
477
        _delay_us(200); //Fet switch delay
478
        setForwardHigh();
479
        state = forward; //Up
480
        sei();
481
    }
482
}
483
484
void braking() {
485
486
    if (state != brake) {
487
        cli();
488
489
        //Clear unused pins
490
        clrForwardHigh();
491
        clrBackwardHigh();
492
        _delay_us(200); //Fet switch delay
493
        setForwardLow();
494
        setBackwardLow();
495
        state = brake;
496
        _delay_ms(10);
497
        sei();
498
    }
499
}
500
501
void goBackwards() {
502
    if (state != backward) {
503
        cli();
504
505
        //Clear high
506
        clrForwardHigh();
507
        clrForwardLow();
508
        _delay_us(200); //Fet switch delay
509
        setBackwardLow();
510
        _delay_us(200); //Fet switch delay
511
        setBackwardHigh();
512
        state = backward;
513
        sei();
514
    }
515
}
516
517
void motorBeep(uint8_t length) {
518
    OCR2 = 10;
519
    uint8_t count = 0;
520
    while (count < length) {
521
        if (count % 2) {
522
            goForwards();
523
        } else {
524
            goBackwards();
525
        }
526
        _delay_ms(200);
527
        count++;
528
        braking();
529
        _delay_ms(300);
530
    }
531
    braking();
532
    OCR2 = 0;
533
}
534
535
void fastBeep(uint8_t length) {
536
    OCR2 = 20;
537
    uint8_t count = 0;
538
    while (count < length) {
539
        if (count % 2) {
540
            goForwards();
541
        } else {
542
            goBackwards();
543
        }
544
        _delay_ms(50);
545
        count++;
546
        braking();
547
        _delay_ms(100);
548
    }
549
    braking();
550
    OCR2 = 0;
551
}
552
553
void waitForState(uint8_t waitForState) {
554
    while (newState != waitForState || failsafe < 13) {
555
        _delay_ms(100);
556
    }
557
}
558
559
void readData() {
560
    //if we have valid EEPROM data read it in
561
    if (eeprom_read_word(&storedRcLow) != 0xFFFF) {
562
        rcLow = eeprom_read_word(&storedRcLow);
563
        rcHigh = eeprom_read_word(&storedRcHigh);
564
        rcMid = (rcLow + rcHigh) / 2;
565
    }
566
    if (eeprom_read_byte(&storedSlewRate) != 0xFF) {
567
        maxSlew = eeprom_read_byte(&storedSlewRate);
568
    }
569
    if (eeprom_read_byte(&storedTempLimit) != 0xFF) {
570
        tempLimit = eeprom_read_byte(&storedTempLimit);
571
    }
572
    if (eeprom_read_byte(&storedExpo) != 0xFF) {
573
        goExpo = eeprom_read_byte(&storedExpo);
574
    }
575
}
576
577
void calibrateRC() {
578
    uint16_t min = 10000;
579
    uint16_t max = 1;
580
    fastBeep(6);
581
    _delay_ms(700);
582
583
    //Move stick all the way down                     
584
    waitForState(backward);
585
    motorBeep(1);
586
    while (newState == backward || newState == brake) {
587
        if (min > rcTime && min > RC_LOW / 2) {
588
            min = rcTime;
589
        }
590
        if (max < rcTime && max < RC_HIGH * 3 / 2) {
591
            max = rcTime;
592
        }
593
    }
594
    motorBeep(2);
595
    waitForState(forward);
596
    while (newState == forward || newState == brake) {
597
        if (min > rcTime && rcTime > RC_LOW * 2 / 3) {
598
            min = rcTime;
599
        }
600
        if (max < rcTime && rcTime < RC_HIGH * 3 / 2) {
601
            max = rcTime;
602
        }
603
    }
604
    motorBeep(3);
605
    eeprom_write_word(&storedRcLow, min);
606
    eeprom_write_word(&storedRcHigh, max);
607
}
608
609
void setSlewRate() {
610
    fastBeep(6);
611
    //Wait for stick to center
612
    waitForState(brake);
613
    _delay_ms(1000);
614
    motorBeep(1);
615
616
    while (newState == brake) {
617
        _delay_ms(1000);
618
    }
619
    uint8_t loop = 1;
620
    uint8_t slew = 2;
621
    while (loop) {
622
        if (newState == forward) {
623
            if (slew < 10) {
624
                slew++;
625
            }
626
            motorBeep(slew);
627
            _delay_ms(1000);
628
        }
629
630
        if (newState == backward) {
631
            if (slew > 1) {
632
                slew--;
633
            }
634
            motorBeep(slew);
635
            _delay_ms(1000);
636
        }
637
638
        if (newState == brake) {
639
            _delay_ms(1000);
640
            if (newState == brake) {
641
                _delay_ms(1000);
642
                if (newState == brake) {
643
                    motorBeep(slew);
644
                    if (F_CPU == 8000000){
645
                        slew = slew * 2;
646
                    }
647
                    eeprom_write_byte(&storedSlewRate, slew);
648
                    loop = 0;
649
                }
650
            }
651
        }
652
    }
653
}
654
655
void setExpo() {
656
    fastBeep(6);
657
    //Wait for stick to center
658
    waitForState(brake);
659
    _delay_ms(1000);
660
    motorBeep(1);
661
662
    while (newState == brake) {
663
        _delay_ms(1000);
664
    }
665
666
    if (newState == forward) {
667
        eeprom_write_byte(&storedExpo, 1);
668
        motorBeep(3);
669
        _delay_ms(1000);
670
    }
671
672
    if (newState == backward) {
673
        eeprom_write_byte(&storedExpo, 0);
674
        motorBeep(4);
675
        _delay_ms(1000);
676
    }
677
}
678
679
void setTempLimit() {
680
    fastBeep(6);
681
    //Wait for stick to center
682
    waitForState(brake);
683
    _delay_ms(1000);
684
    motorBeep(1);
685
686
    while (newState == brake) {
687
        _delay_ms(1000);
688
    }
689
690
    if (newState == forward) {
691
        eeprom_write_byte(&storedTempLimit, 1);
692
        motorBeep(3);
693
        _delay_ms(1000);
694
    }
695
696
    if (newState == backward) {
697
        eeprom_write_byte(&storedTempLimit, 0);
698
        motorBeep(4);
699
        _delay_ms(1000);
700
    }
701
}

von Karl H. (kbuchegg)


Lesenswert?

Ich hätte mal gesagt, dass für Vorwärts fahren, die gesuchte Stelle hier 
zu finden ist
1
                    if (time_diff > (rcHigh - maxOut)) {
2
                        desiredPWM = 255;
3
                    } else {
4
                        desiredPWM = (time_diff - rcMid - deadzone)*256 / (rcHigh - rcMid - deadzone);

Die Zuweisung von 255 dürfte für Vollgas verantwortlich sein.
D.h. der Wert von time_diff ist grösser als rcHigh bzw. rcHigh - maxOut. 
Enteder ist rcHigh zu klein gesetzt oder maxOut zu gross.

rcHigh kommt von hier
1
volatile uint16_t rcLow = RC_LOW;
2
volatile uint16_t rcHigh = RC_HIGH;

und die Makrodefinition kann ich nicht sehen. Steckt wahrscheinlich im 
Header File
1
#include "../pindefs/tz85a.h"
oder wird per Makefile Option vorgegeben. Aber irgendwo muss er sein.
Selbiges für
1
        uint8_t maxOut = MAXOUTTIME;

Du kannst ja mal probieren, ob wir überhaupt an der richtigen Stelle 
sind.
Wenn du die 255 änderst zu
1
                    if (time_diff > (rcHigh - maxOut)) {
2
                        desiredPWM = 128;
dann sollte der Motor eigentlich bei überschreiten deiner ominösen 75% 
anstatt auf Vollgas einfach auf 0 gehen, wenn ich die Funktion der PWM 
auf die Schnelle richtig erkannt habe.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Halt. Kommando retour.
Die High und Low Werte kommen aus dem EEPROM und werden kalibriert. D.h. 
wenn der MAXOUTTIME nicht aberwitzig hoch ist, dann ist deine 
Kalibrierung des Reglers an deine Fernsteueranlage einfach nur mies oder 
gar nicht durchgeführt worden.

: Bearbeitet durch User
von Andre Meschke (Gast)


Lesenswert?

Hallo,
auf Null zu gehen wäre auch nicht ganz richtig,

: Bearbeitet durch User
von Andre Meschke (Gast)


Lesenswert?

Die Kalibrierung hab ich gemacht.

von Karl H. (kbuchegg)


Lesenswert?

Andre Meschke schrieb:
> Hallo,
> auf Null zu gehen wäre auch nicht ganz richtig,


das weiss ich schon.

Aber ehe ich da jetzt grossartig weiter analysiere, will ich erst mal 
wissen, ob die auf dem schnellen Weg identifizierte Programmposition 
überhaupt die richtige Stelle ist. Und dazu schlage ich eine 
Modifikation vor, dessen Auswirkung sofort und ohne Messgerät leicht zu 
sehen und zu überprüfen ist. Was einfacheres als "anstelle von 100% geht 
der Motor in den Stillstand (oder Halbgas?)" kann ich mir kaum 
vorstellen. Passiert das tatsächlich, dann weiss ich, dass das hier die 
richtige Codestelle ist und spar mir die Analyse der restlichen 48 
Seiten Code. Und dann sehen wir weiter, wie es zu diesem Problem kommen 
kann.



PS: Sorry. Ich hab irrtümlich auf 'Bearbeiten' geklickt anstatt auf 
'Antworten'.
Kannst du das Header File noch mal posten`?

: Bearbeitet durch User
von Andre Meschke (Gast)


Lesenswert?

1
/* -----------------------------
2
3
ESC Name:         F20A
4
Current Rating:   20A
5
Added by:         Steven Martin
6
Date:             4/04/2011
7
Tested by:        
8
Date:             
9
10
Comments:
11
Has same pinout as TZ85a         
12
Still would not classify as battle tested.
13
14
------------------------------- */
15
//Need to setup the high and low sides
16
//Must set direction port, port and pin. 
17
18
//Channel A
19
#define SET_HIGH_A_PORT DDRD
20
#define HIGH_A_PORT PORTD
21
#define HIGH_A 4
22
23
#define SET_LOW_A_PORT DDRD
24
#define LOW_A_PORT PORTD
25
#define LOW_A  5
26
27
//Channel B
28
#define SET_HIGH_B_PORT DDRC
29
#define HIGH_B_PORT PORTC
30
#define HIGH_B  5
31
32
#define SET_LOW_B_PORT DDRC
33
#define LOW_B_PORT PORTC
34
#define LOW_B  4
35
36
//Channel C
37
#define SET_HIGH_C_PORT DDRC
38
#define HIGH_C_PORT PORTC
39
#define HIGH_C 3
40
41
#define SET_LOW_C_PORT DDRB
42
#define LOW_C_PORT PORTB
43
#define LOW_C  0
44
45
//Are we using active low.
46
#define LOW_ACTIVE_LOW 0
47
#define HIGH_ACTIVE_LOW 1
48
49
50
//Also we need to setup the RC inputs
51
52
//RC Pins
53
#define SET_RC_PORT DDRD
54
55
#define RC_PORT PIND
56
57
#define RC_PIN  2
58
59
#define RC_LOW  260//150
60
#define RC_HIGH 480//400
61
#define RC_MID 370//275
62
63
/* There is also lots of connections for inputs from ADC and stuff but that can be added later
64
   if we want to be able to monitor battery voltage could also look at back EMF and some other stuff */
65
66
//RC Time variables 
67
#define DEADTIME 10
68
#define BUFFERTIME 40
69
#define MAXOUTTIME 20
70
71
//Do we want to be able to calibrate stuff
72
#define CALIBRATION 0
73
74
//Do you want EXPO Rates
75
#define EXPO 0
76
77
//Do you want TEMP LIMITING
78
#define TEMP_LIMIT 0
79
80
//Max Slew rate
81
#define MAX_SLEW  2 //Change in PWM 0-255 per clock tick (500Hz @ 8MHZ or 1Khz @ 16Mhz)
82
83
//Set temperature ADC Pin
84
#define TEMP_ADMUX 0b00000001  //ADC mux 1
85
#define I_AM_WARM 180
86
#define I_AM_HOT  170
87
88
//Define cpu speed
89
#define F_CPU 16000000UL
Die define RC Parameter hab ich mir schon angepasst
hat aber keine Auswirkung auf das andere Problem.
Deinen Vorschlag probier gleich noch aus.

von Andre Meschke (Gast)


Lesenswert?

Die Zeile in der das time_diff steht hab ich den Wert wie du gesagt hast 
geändert auf 128. Ergebnis bei Überschreitung der 75% Schwelle wird der 
Motor langsamer.
Die 75% sind nur ein geschätzter Wert.

von Karl H. (kbuchegg)


Lesenswert?

Hier
1
#define MAXOUTTIME 20
mach da mal eine 0 draus anstelle der 20

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Andre Meschke schrieb:
> Die Zeile in der das time_diff steht hab ich den Wert wie du gesagt hast
> geändert auf 128. Ergebnis bei Überschreitung der 75% Schwelle wird der
> Motor langsamer.

Gut.
Dann bin ich mir recht sicher, dass das die bewusste Stelle ist.

Das scheint Absicht zu sein. Etwas für Rennfahrer, die immer Vollgas 
haben wollen, auch wenn der Knüppel im Eifer des Gefechts einmal aus der 
Endposition irrtümlich herausbewegt wird.

Also die 128 wieder auf 255 zurück ändern. Der Zweck der Übung (die 
Kontrolle) wurde ja erreicht.

: Bearbeitet durch User
von Andre Meschke (Gast)


Lesenswert?

Der Code ist für Fighting Robots gedacht. Ich fahre aber ein Scale 
Schiffsmodell. Lässt sich das irgendwie ändern?

von Karl H. (kbuchegg)


Lesenswert?

Andre Meschke schrieb:
> Der Code ist für Fighting Robots gedacht. Ich fahre aber ein Scale
> Schiffsmodell. Lässt sich das irgendwie ändern?

Sag ich doch
Beitrag "Re: C-Code für Fahrtregler anpassen"

von Andre Meschke (Gast)


Lesenswert?

Hab jetzt im Hedaer folgende Zeile geändert
#define MAXOUTTIME 20
den Wert hab ich auf Null gesetzt, da gibt es dann fast keinen Sprung 
mehr.
Vielleicht hast du noch ne bessere Idee.

von Karl H. (kbuchegg)


Lesenswert?

Andre Meschke schrieb:

> Vielleicht hast du noch ne bessere Idee.

Mehr sieht der Code nicht vor.
Kalibriere noch einmal, wobei du diesmal bei den Endwerten die Trimmung 
noch in der jeweiligen Richtung mit dazu nimmst. Wenn dein Sender eine 
Servoweg Einstellung erlaubt, kannst du auch mit der den Ausgabewert in 
der Vollgasposition ein wenig kleiner machen.

Für den Rest bräuchte man jetzt die konkreten Zahlen, die sich aus der 
Kalibrierung auf dem µC ergeben haben um einmal nachzurechnen, welche 
Werte sich hier
1
  desiredPWM = (time_diff - rcMid - deadzone)*256 / (rcHigh - rcMid - deadzone);
eigentlich ergeben und ob es da einen rechnerischen Zahlensprung gibt.
Die Zahlen wirst du aber nicht haben.

von Karl H. (kbuchegg)


Lesenswert?

Karl H. schrieb:

>
1
>   desiredPWM = (time_diff - rcMid - deadzone)*256 / (rcHigh - rcMid - 
2
> deadzone);
3
>

Hmm.
Man könnte hier vielleicht noch eine Rundungskorrektur anbringen
1
  desiredPWM = (time_diff - rcMid - deadzone + ((rcHigh - rcMid - deadzone) / 2 ))*256 / (rcHigh - rcMid - deadzone) ;

Probier dann aber auch die kleinen Fahrstufen noch mit aus.
(UNd dann die Formel wieder etwas vereinfachen :-)

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl H. schrieb:
> Karl H. schrieb:
>
>>
1
>>   desiredPWM = (time_diff - rcMid - deadzone)*256 / (rcHigh - rcMid -
2
>> deadzone);
3
>>
>
> Hmm.
> Man könnte hier vielleicht noch eine Rundungskorrektur anbringen
>
1
>   desiredPWM = (time_diff - rcMid - deadzone + ((rcHigh - rcMid - 
2
> deadzone) / 2 ))*256 / (rcHigh - rcMid - deadzone) ;
3
>
>
> Probier dann aber auch die kleinen Fahrstufen noch mit aus.
> (UNd dann die Formel wieder etwas vereinfachen :-)

What the heck. So rum wirds schon um einiges simpler
1
                    } else {
2
                        uint16_t divisor = rcHigh - rcMid - deadzone;
3
                        desiredPWM = (time_diff - rcMid - deadzone + divisor/2)*256 / divisor;
4
 ...

                        i

von Andre Meschke (Gast)


Lesenswert?

Die letzte Vereinfachung raff ich zwar noch nicht ganz.
Die Werte der Kalibrierung hab ich ja

RC_LOW  260
RC_HIGH 480
RC_MID 370

An welche Stelle kommt das hier rein

 } else {
                        uint16_t divisor = rcHigh - rcMid - deadzone;
                        desiredPWM = (time_diff - rcMid - deadzone + 
divisor/2)*256 / divisor;

und was muss ich dafür entfernen

von Karl H. (kbuchegg)


Lesenswert?

Andre Meschke schrieb:
> Die letzte Vereinfachung raff ich zwar noch nicht ganz.

Ich habe einfach nur den Ausdruck durch den dividiert wird in eine 
eigene Zwischenvariable geholt. Dies deshalb, damit ich den Nenner bei 
der Division noch die Hälfte davon dazuzählen kann ohne dass ich mir die 
Finger wund tippe. Eine sog. Rundungskorrektur.
In C wird bei Divisionen kein Nachkommaanteil beim rechnen mit Integern 
erzeugt. Die Division
1
6 / 7
ergibt eine glatte 0. Wenn ich aber das mit einem Taschenrechner 
ausrechne, dann bringt der 0.857.. raus. Und das liegt schon wesentlich 
näher an 1 als es an 0 liegt. D.h was ich gerne haben möchte, das ist 
das mir bei Divisionen, die einen Nachkommaanteil größer/gleich 0.5 
rausbringen würden, dann auch die nächst höhere Zahl als Ergebnis kommt. 
Eben so, wie wenn ich die 0.857 runden würde und 1.0 herausbringen 
würde.
Und dazu rechne ich nicht
1
   a
2
 ----- 
3
   b
sondern
1
   a
2
 ----- + 0.5
3
   b

dann kommt mir bei der Division
1
6 / 7  -> 0.857
2
0.857 + 0.5 -> 1.3357
heraus, und wenn man da die Nachkommastellen weglässt, dann erhalte ich 
die gewünschte 1

Aber: So will ich das nicht rechnen, weil ich ja keine 
Fliesskommaoperationen haben will. Aber ich kann ja die 0.5 auf den 
Bruchstrich hinaufziehen indem ich die 0.5 (oder eben 1/2) mit b 
erweitere. Und lande so bei
1
   a + b/2
2
  ---------
3
      b
und das kann ich wieder komplett mit ganzen Zahlen rechnen
1
   6 + 3        9
2
  -------  = -------
3
      7         7
( 3 ist die Hälfte von 7, wenn keine Nachkommastellen zugelassen sind)
und jetzt kommt auch wieder die gewünschte (gerundete, na ja) 1 heraus 
anstatt der ursprünglichen 0.
Habe ich statt dessen 2 / 7 zu rechnen, dann ist das Ergebnis
1
    2 + 3
2
  ---------
3
      7
und das ergibt 5 / 7 oder eben ausgerechnet eine glatte 0. Und das ist 
auch gut so, denn 2/7 oder in Fiesskomma gerechnet 0.28 liegt näher an 0 
als an 1.

> RC_LOW  260
> RC_HIGH 480
> RC_MID 370

Na dann setz die Zahlenwerte mal ein und rechne mal aus, was da dann für 
desiredPWM herauskommt.

> Die Werte der Kalibrierung hab ich ja

Woher hast du die? Waren die schon eingetragen?

-> Die müssen nicht notwendigerweise mit deiner Fernsteuerung 
zusammenpassen. Kalibrieren bedeutet, dass du den Regler in die 
Kalbrierung bringst, dann auf der Fernsteuerung deinen Knüppel in die 
Endposition bewegst und dem Regler mitteilst: das wars, jetzt ist der 
Knüppel in der Endposition, den Wert den du jetzt vermisst, dass ist der 
Wert der als Endposition gelten soll.

hast du das so gemacht und so die Werte ermittelt?

>  } else {
>                         uint16_t divisor = rcHigh - rcMid - deadzone;
>                         desiredPWM = (time_diff - rcMid - deadzone +
> divisor/2)*256 / divisor;
>
> und was muss ich dafür entfernen

Na da, wo vorher
1
                } else { //Else go forward
2
                    if (time_diff > (rcHigh - maxOut)) {
3
                        desiredPWM = 255;
4
                    } else {
5
                        desiredPWM = (time_diff - rcMid - deadzone)*256 / (rcHigh - rcMid - deadzone);
6
....
7
....
stand, da kommt jetzt
1
                } else { //Else go forward
2
                    if (time_diff > (rcHigh - maxOut)) {
3
                        desiredPWM = 255;
4
                    } else {
5
                        uint16_t divisor = rcHigh - rcMid - deadzone;
6
                        desiredPWM = (time_diff - rcMid - deadzone + divisor/2)*256 / divisor;
7
.....

Es ist seit Stunden immer die gleiche Codestelle.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Ui.
Das ist vielleicht ein Durcheinander in diesem Programm.
Auf der einen Seite gibt es eine Kalibrierfunktion, die irgendwelche 
Werte ermittelt und ins EEPROM schreibt. Auf der anderen Seite ist der 
Aufruf der Funktion, die die Kalbrierwerte aus dem EEPROM zum arbeiten 
holen sollte, auskommentiert.

So einen Saustall hab ich auch schon lange nicht mehr gesehen. Und das 
veröffentlicht jemand genau so?

von Karl H. (kbuchegg)


Lesenswert?

DU könntest hier
1
RC_HIGH 480
noch probieren, den Wert etwas höher setzen. Sagen wir mal 485 oder 490.

von Andre Meschke (Gast)


Lesenswert?

Ja das gibt es hier. War ein schönes Projekt. Aus preiswerten 
Brushlessreglern wurden Brushregler gemacht weil es die kaum noch 
preiswert gibt.
http://bazaar.launchpad.net/~brushed-team/brushed/trunk/files
Derjenige hat die Opensource Entwicklung eingestellt und vermarktet das 
jetzt hier.
http://botbitz.com.au/index.php?route=product/category&path=60

von Karl H. (kbuchegg)


Lesenswert?

Andre Meschke schrieb:

> Derjenige hat die Opensource Entwicklung eingestellt und vermarktet das
> jetzt hier.
> http://botbitz.com.au/index.php?route=product/category&path=60

Dann wollen wir mal hoffen, dass sein Produktionscode in einem besseren 
Zustand ist.

von Matthias L. (Gast)


Lesenswert?

Karl H. schrieb:
> So einen Saustall hab ich auch schon lange nicht mehr gesehen. Und das
> veröffentlicht jemand genau so?

Ja, wäre der Code in asm würde man sowas nur durch UVS erkennen ;-)

von Andre Meschke (Gast)


Lesenswert?

OK ich glaub du hast recht da habe ich mir wohl den falschen Coder 
rausgesucht.
Hier ist noch ein in Assembler programmierter Code von jemand Anderem.
Auch der hat für mich nen kleinen Haken, ich hätte gern ein Deathband im 
Bereich zwischen 1179 und 1219 damit der Motor auch wirklich steht und 0 
Volt hat. Kann man in dem Assembler Code noch etwas ändern? Ein Paar 
Werte hab ich schon an meine Fernbedienung angepasst.
1
;--- Brushed ESC By Rolf R Bakke, May 2012
2
3
.include "m8def.inc"
4
5
.include "macros.inc"
6
7
.def  t=r16
8
9
.org 0
10
  ldi t, low(ramend)
11
  out spl, t
12
  ldi t, high(ramend)
13
  out sph, t
14
15
16
  ;--- Port setup ---
17
18
  ;        76543210
19
  ldi t, 0b11001100
20
  out ddrc, t
21
22
  ;        76543210
23
  ldi t, 0b11111111
24
  out ddrb, t
25
26
  ;        76543210
27
  ldi t, 0b10111011
28
  out ddrd, t
29
30
31
  ;--- PWM output setup ---
32
33
  ;        76543210
34
  ldi t, 0b10100000  
35
  out tccr1a, t
36
37
  ;        76543210
38
  ldi t, 0b00010001
39
  out tccr1b, t
40
41
  ldi t, high(255)  ;set PWM range
42
  out icr1h, t
43
  ldi t, low(255)
44
  out icr1l, t
45
46
47
  ;--- arming ---
48
49
ar2:  ldi zl, 0
50
51
ar1:  rcall GetPwm
52
  brcs ar2    ;time out, reset counter
53
  
54
  ldy 1159    ;1180 orginaler Wert im Code
55
  cp  xl, yl
56
  cpc xh, yh
57
  brlo ar2    ;too low, reset counter
58
59
  ldy 1239    ;1220 orginaler Wert im Code
60
  cp  xl, yl
61
  cpc xh, yh
62
  brsh ar2    ;too high, reset counter
63
64
  inc zl      ;in range, increase counter
65
  cpi zl, 50    ;50 in a row?
66
  brne ar1    ;no, arming not OK
67
68
69
  ;--- Main loop ---
70
71
ma1:  rcall GetPwm    ;get input PWM value
72
73
  subi xl, low(1199)  ;subtract 1500 uS    1200 orginaler Wert im Code 
74
  sbci xh, high(1199)            ;1200 orginaler Wert im Code
75
76
  brcs ma4    ;wich direction?
77
78
79
  ;--- forward ---
80
81
  clr t      ;turn off B half-bridge PWM
82
  out ocr1bh, t
83
  out ocr1bl, t
84
  rcall delay    ;wait one PWM cycle to let the B PWM hardware finish it current cycle
85
  a_top_off    ;set top transistors for forward configuration
86
  b_top_on
87
  out ocr1ah, xh    ;update A half-bridge with current throttle
88
  out ocr1al, xl
89
90
  rjmp ma1
91
92
93
  ;--- reverse ---
94
95
ma4:  clr yl      ;Y = NEG(X)
96
  clr yh
97
  sub yl, xl
98
  sbc yh, xh
99
100
  clr t      ;turn off A half-bridge PWM
101
  out ocr1ah, t
102
  out ocr1al, t
103
  rcall delay    ;wait one PWM cycle to let the A PWM hardware finish it current cycle
104
  b_top_off    ;set top transistors for reverse configuration
105
  a_top_on
106
  out ocr1bh, yh    ;update B half-bridge with current throttle
107
  out ocr1bl, yl
108
109
  rjmp ma1
110
111
112
  ;--- SUBS ---
113
114
  ;--- delay ----
115
  
116
117
delay:  ldi t, 0    ;96 uS delay
118
de1:  dec t
119
  brne de1
120
  ret
121
122
  
123
124
  ;--- get PWM input value ---
125
126
127
GetPwm:
128
  clr xl
129
  clr xh
130
131
  ;wait for low to high transition on ppm input
132
133
  ldy 0xffff
134
ge1:  sbiw y, 1
135
  brcs ge5  ;timeout (49mS)
136
  sbic pind, 2
137
  rjmp ge1
138
139
  ldy 0xffff    
140
ge2:  sbiw y,1
141
  brcs ge5  ;timeout (49mS)
142
  sbis pind, 2
143
  rjmp ge2
144
145
  ;measure high pulse time, 1.25 uS = 1 count
146
147
  ldy 8000
148
ge3:  adiw x, 1  ;2
149
  sbiw y, 1  ;2
150
  brcs ge5  ;1  ;exit with c=1 if timeout (10mS)
151
  nop    ;1
152
  nop    ;1
153
  sbic pind, 2  ;1
154
  rjmp ge3  ;2
155
156
  ;set to 1500uS if below 900uS or above 2100uS
157
158
  ldy 720
159
  cp  xl, yl
160
  cpc xh, yh
161
  brlo ge4  
162
  ldy 1680
163
  cp  xl, yl
164
  cpc xh, yh
165
  brlo ge6  
166
167
ge4:  ldx 1199    ;out of limits, set to 1500uS     1200 orginaler Wert im Code
168
169
  ;
170
171
ge6:  clc      ;exit with c=0 if no timeout
172
  ret
173
174
ge5:  ldx 1199    ;time out, set to 1500uS and c=1  1200 orginaler Wert im Code
175
  ret

Hier noch die Include Dateien:
1
.macro  a_top_on
2
  sbi portd, 4
3
.endmacro
4
5
.macro  a_top_off
6
  cbi portd, 4
7
.endmacro
8
9
10
11
.macro  b_top_on
12
  sbi portd, 5
13
.endmacro
14
15
.macro  b_top_off
16
  cbi portd, 5
17
.endmacro
18
19
20
21
22
.macro  ldx
23
  ldi xl, low(@0)
24
  ldi xh, high(@0)
25
.endmacro
26
.macro  ldy
27
  ldi yl, low(@0)
28
  ldi yh, high(@0)
29
.endmacro
30
.macro  ldz
31
  ldi zl, low(@0)
32
  ldi zh, high(@0)
33
.endmacro
34
 
35
36
37
38
.macro  debug_on
39
  sbi portb, 5
40
.endmacro
41
42
.macro  debug_off
43
  cbi portb, 5
44
.endmacro
1
;***** THIS IS A MACHINE GENERATED FILE - DO NOT EDIT ********************
2
;***** Created: 2011-08-25 21:00 ******* Source: ATmega8.xml *************
3
;*************************************************************************
4
;* A P P L I C A T I O N   N O T E   F O R   T H E   A V R   F A M I L Y
5
;* 
6
;* Number            : AVR000
7
;* File Name         : "m8def.inc"
8
;* Title             : Register/Bit Definitions for the ATmega8
9
;* Date              : 2011-08-25
10
;* Version           : 2.35
11
;* Support E-mail    : avr@atmel.com
12
;* Target MCU        : ATmega8
13
;* 
14
;* DESCRIPTION
15
;* When including this file in the assembly program file, all I/O register 
16
;* names and I/O register bit names appearing in the data book can be used.
17
;* In addition, the six registers forming the three data pointers X, Y and 
18
;* Z have been assigned names XL - ZH. Highest RAM address for Internal 
19
;* SRAM is also defined 
20
;* 
21
;* The Register names are represented by their hexadecimal address.
22
;* 
23
;* The Register Bit names are represented by their bit number (0-7).
24
;* 
25
;* Please observe the difference in using the bit names with instructions
26
;* such as "sbr"/"cbr" (set/clear bit in register) and "sbrs"/"sbrc"
27
;* (skip if bit in register set/cleared). The following example illustrates
28
;* this:
29
;* 
30
;* in    r16,PORTB             ;read PORTB latch
31
;* sbr   r16,(1<<PB6)+(1<<PB5) ;set PB6 and PB5 (use masks, not bit#)
32
;* out   PORTB,r16             ;output to PORTB
33
;* 
34
;* in    r16,TIFR              ;read the Timer Interrupt Flag Register
35
;* sbrc  r16,TOV0              ;test the overflow flag (use bit#)
36
;* rjmp  TOV0_is_set           ;jump if set
37
;* ...                         ;otherwise do something else
38
;*************************************************************************
39
40
#ifndef _M8DEF_INC_
41
#define _M8DEF_INC_
42
43
44
#pragma partinc 0
45
46
; ***** SPECIFY DEVICE ***************************************************
47
.device ATmega8
48
#pragma AVRPART ADMIN PART_NAME ATmega8
49
.equ  SIGNATURE_000  = 0x1e
50
.equ  SIGNATURE_001  = 0x93
51
.equ  SIGNATURE_002  = 0x07
52
53
#pragma AVRPART CORE CORE_VERSION V2E
54
55
56
; ***** I/O REGISTER DEFINITIONS *****************************************
57
; NOTE:
58
; Definitions marked "MEMORY MAPPED"are extended I/O ports
59
; and cannot be used with IN/OUT instructions
60
.equ  SREG  = 0x3f
61
.equ  SPL  = 0x3d
62
.equ  SPH  = 0x3e
63
.equ  GICR  = 0x3b
64
.equ  GIFR  = 0x3a
65
.equ  TIMSK  = 0x39
66
.equ  TIFR  = 0x38
67
.equ  SPMCR  = 0x37
68
.equ  TWCR  = 0x36
69
.equ  MCUCR  = 0x35
70
.equ  MCUCSR  = 0x34
71
.equ  TCCR0  = 0x33
72
.equ  TCNT0  = 0x32
73
.equ  OSCCAL  = 0x31
74
.equ  SFIOR  = 0x30
75
.equ  TCCR1A  = 0x2f
76
.equ  TCCR1B  = 0x2e
77
.equ  TCNT1L  = 0x2c
78
.equ  TCNT1H  = 0x2d
79
.equ  OCR1AL  = 0x2a
80
.equ  OCR1AH  = 0x2b
81
.equ  OCR1BL  = 0x28
82
.equ  OCR1BH  = 0x29
83
.equ  ICR1L  = 0x26
84
.equ  ICR1H  = 0x27
85
.equ  TCCR2  = 0x25
86
.equ  TCNT2  = 0x24
87
.equ  OCR2  = 0x23
88
.equ  ASSR  = 0x22
89
.equ  WDTCR  = 0x21
90
.equ  UBRRH  = 0x20
91
.equ  UCSRC  = 0x20
92
.equ  EEARL  = 0x1e
93
.equ  EEARH  = 0x1f
94
.equ  EEDR  = 0x1d
95
.equ  EECR  = 0x1c
96
.equ  PORTB  = 0x18
97
.equ  DDRB  = 0x17
98
.equ  PINB  = 0x16
99
.equ  PORTC  = 0x15
100
.equ  DDRC  = 0x14
101
.equ  PINC  = 0x13
102
.equ  PORTD  = 0x12
103
.equ  DDRD  = 0x11
104
.equ  PIND  = 0x10
105
.equ  SPDR  = 0x0f
106
.equ  SPSR  = 0x0e
107
.equ  SPCR  = 0x0d
108
.equ  UDR  = 0x0c
109
.equ  UCSRA  = 0x0b
110
.equ  UCSRB  = 0x0a
111
.equ  UBRRL  = 0x09
112
.equ  ACSR  = 0x08
113
.equ  ADMUX  = 0x07
114
.equ  ADCSRA  = 0x06
115
.equ  ADCL  = 0x04
116
.equ  ADCH  = 0x05
117
.equ  TWDR  = 0x03
118
.equ  TWAR  = 0x02
119
.equ  TWSR  = 0x01
120
.equ  TWBR  = 0x00
121
122
123
; ***** BIT DEFINITIONS **************************************************
124
125
; ***** ANALOG_COMPARATOR ************
126
; SFIOR - Special Function IO Register
127
.equ  ACME  = 3  ; Analog Comparator Multiplexer Enable
128
129
; ACSR - Analog Comparator Control And Status Register
130
.equ  ACIS0  = 0  ; Analog Comparator Interrupt Mode Select bit 0
131
.equ  ACIS1  = 1  ; Analog Comparator Interrupt Mode Select bit 1
132
.equ  ACIC  = 2  ; Analog Comparator Input Capture Enable
133
.equ  ACIE  = 3  ; Analog Comparator Interrupt Enable
134
.equ  ACI  = 4  ; Analog Comparator Interrupt Flag
135
.equ  ACO  = 5  ; Analog Compare Output
136
.equ  ACBG  = 6  ; Analog Comparator Bandgap Select
137
.equ  ACD  = 7  ; Analog Comparator Disable
138
139
140
; ***** SPI **************************
141
; SPDR - SPI Data Register
142
.equ  SPDR0  = 0  ; SPI Data Register bit 0
143
.equ  SPDR1  = 1  ; SPI Data Register bit 1
144
.equ  SPDR2  = 2  ; SPI Data Register bit 2
145
.equ  SPDR3  = 3  ; SPI Data Register bit 3
146
.equ  SPDR4  = 4  ; SPI Data Register bit 4
147
.equ  SPDR5  = 5  ; SPI Data Register bit 5
148
.equ  SPDR6  = 6  ; SPI Data Register bit 6
149
.equ  SPDR7  = 7  ; SPI Data Register bit 7
150
151
; SPSR - SPI Status Register
152
.equ  SPI2X  = 0  ; Double SPI Speed Bit
153
.equ  WCOL  = 6  ; Write Collision Flag
154
.equ  SPIF  = 7  ; SPI Interrupt Flag
155
156
; SPCR - SPI Control Register
157
.equ  SPR0  = 0  ; SPI Clock Rate Select 0
158
.equ  SPR1  = 1  ; SPI Clock Rate Select 1
159
.equ  CPHA  = 2  ; Clock Phase
160
.equ  CPOL  = 3  ; Clock polarity
161
.equ  MSTR  = 4  ; Master/Slave Select
162
.equ  DORD  = 5  ; Data Order
163
.equ  SPE  = 6  ; SPI Enable
164
.equ  SPIE  = 7  ; SPI Interrupt Enable
165
166
167
; ***** EXTERNAL_INTERRUPT ***********
168
; GICR - General Interrupt Control Register
169
.equ  GIMSK  = GICR  ; For compatibility
170
.equ  IVCE  = 0  ; Interrupt Vector Change Enable
171
.equ  IVSEL  = 1  ; Interrupt Vector Select
172
.equ  INT0  = 6  ; External Interrupt Request 0 Enable
173
.equ  INT1  = 7  ; External Interrupt Request 1 Enable
174
175
; GIFR - General Interrupt Flag Register
176
.equ  INTF0  = 6  ; External Interrupt Flag 0
177
.equ  INTF1  = 7  ; External Interrupt Flag 1
178
179
; MCUCR - MCU Control Register
180
.equ  ISC00  = 0  ; Interrupt Sense Control 0 Bit 0
181
.equ  ISC01  = 1  ; Interrupt Sense Control 0 Bit 1
182
.equ  ISC10  = 2  ; Interrupt Sense Control 1 Bit 0
183
.equ  ISC11  = 3  ; Interrupt Sense Control 1 Bit 1
184
185
186
; ***** TIMER_COUNTER_0 **************
187
; TIMSK - Timer/Counter Interrupt Mask Register
188
.equ  TOIE0  = 0  ; Timer/Counter0 Overflow Interrupt Enable
189
190
; TIFR - Timer/Counter Interrupt Flag register
191
.equ  TOV0  = 0  ; Timer/Counter0 Overflow Flag
192
193
; TCCR0 - Timer/Counter0 Control Register
194
.equ  CS00  = 0  ; Clock Select0 bit 0
195
.equ  CS01  = 1  ; Clock Select0 bit 1
196
.equ  CS02  = 2  ; Clock Select0 bit 2
197
198
; TCNT0 - Timer Counter 0
199
.equ  TCNT00  = 0  ; Timer Counter 0 bit 0
200
.equ  TCNT01  = 1  ; Timer Counter 0 bit 1
201
.equ  TCNT02  = 2  ; Timer Counter 0 bit 2
202
.equ  TCNT03  = 3  ; Timer Counter 0 bit 3
203
.equ  TCNT04  = 4  ; Timer Counter 0 bit 4
204
.equ  TCNT05  = 5  ; Timer Counter 0 bit 5
205
.equ  TCNT06  = 6  ; Timer Counter 0 bit 6
206
.equ  TCNT07  = 7  ; Timer Counter 0 bit 7
207
208
209
; ***** TIMER_COUNTER_1 **************
210
; TIMSK - Timer/Counter Interrupt Mask Register
211
.equ  TOIE1  = 2  ; Timer/Counter1 Overflow Interrupt Enable
212
.equ  OCIE1B  = 3  ; Timer/Counter1 Output CompareB Match Interrupt Enable
213
.equ  OCIE1A  = 4  ; Timer/Counter1 Output CompareA Match Interrupt Enable
214
.equ  TICIE1  = 5  ; Timer/Counter1 Input Capture Interrupt Enable
215
216
; TIFR - Timer/Counter Interrupt Flag register
217
.equ  TOV1  = 2  ; Timer/Counter1 Overflow Flag
218
.equ  OCF1B  = 3  ; Output Compare Flag 1B
219
.equ  OCF1A  = 4  ; Output Compare Flag 1A
220
.equ  ICF1  = 5  ; Input Capture Flag 1
221
222
; TCCR1A - Timer/Counter1 Control Register A
223
.equ  WGM10  = 0  ; Waveform Generation Mode
224
.equ  PWM10  = WGM10  ; For compatibility
225
.equ  WGM11  = 1  ; Waveform Generation Mode
226
.equ  PWM11  = WGM11  ; For compatibility
227
.equ  FOC1B  = 2  ; Force Output Compare 1B
228
.equ  FOC1A  = 3  ; Force Output Compare 1A
229
.equ  COM1B0  = 4  ; Compare Output Mode 1B, bit 0
230
.equ  COM1B1  = 5  ; Compare Output Mode 1B, bit 1
231
.equ  COM1A0  = 6  ; Compare Ouput Mode 1A, bit 0
232
.equ  COM1A1  = 7  ; Compare Output Mode 1A, bit 1
233
234
; TCCR1B - Timer/Counter1 Control Register B
235
.equ  CS10  = 0  ; Prescaler source of Timer/Counter 1
236
.equ  CS11  = 1  ; Prescaler source of Timer/Counter 1
237
.equ  CS12  = 2  ; Prescaler source of Timer/Counter 1
238
.equ  WGM12  = 3  ; Waveform Generation Mode
239
.equ  CTC10  = WGM12  ; For compatibility
240
.equ  CTC1  = WGM12  ; For compatibility
241
.equ  WGM13  = 4  ; Waveform Generation Mode
242
.equ  CTC11  = WGM13  ; For compatibility
243
.equ  ICES1  = 6  ; Input Capture 1 Edge Select
244
.equ  ICNC1  = 7  ; Input Capture 1 Noise Canceler
245
246
247
; ***** TIMER_COUNTER_2 **************
248
; TIMSK - Timer/Counter Interrupt Mask register
249
.equ  TOIE2  = 6  ; Timer/Counter2 Overflow Interrupt Enable
250
.equ  OCIE2  = 7  ; Timer/Counter2 Output Compare Match Interrupt Enable
251
252
; TIFR - Timer/Counter Interrupt Flag Register
253
.equ  TOV2  = 6  ; Timer/Counter2 Overflow Flag
254
.equ  OCF2  = 7  ; Output Compare Flag 2
255
256
; TCCR2 - Timer/Counter2 Control Register
257
.equ  CS20  = 0  ; Clock Select bit 0
258
.equ  CS21  = 1  ; Clock Select bit 1
259
.equ  CS22  = 2  ; Clock Select bit 2
260
.equ  WGM21  = 3  ; Waveform Generation Mode
261
.equ  CTC2  = WGM21  ; For compatibility
262
.equ  COM20  = 4  ; Compare Output Mode bit 0
263
.equ  COM21  = 5  ; Compare Output Mode bit 1
264
.equ  WGM20  = 6  ; Waveform Genration Mode
265
.equ  PWM2  = WGM20  ; For compatibility
266
.equ  FOC2  = 7  ; Force Output Compare
267
268
; TCNT2 - Timer/Counter2
269
.equ  TCNT2_0  = 0  ; Timer/Counter 2 bit 0
270
.equ  TCNT2_1  = 1  ; Timer/Counter 2 bit 1
271
.equ  TCNT2_2  = 2  ; Timer/Counter 2 bit 2
272
.equ  TCNT2_3  = 3  ; Timer/Counter 2 bit 3
273
.equ  TCNT2_4  = 4  ; Timer/Counter 2 bit 4
274
.equ  TCNT2_5  = 5  ; Timer/Counter 2 bit 5
275
.equ  TCNT2_6  = 6  ; Timer/Counter 2 bit 6
276
.equ  TCNT2_7  = 7  ; Timer/Counter 2 bit 7
277
278
; OCR2 - Timer/Counter2 Output Compare Register
279
.equ  OCR2_0  = 0  ; Timer/Counter2 Output Compare Register Bit 0
280
.equ  OCR2_1  = 1  ; Timer/Counter2 Output Compare Register Bit 1
281
.equ  OCR2_2  = 2  ; Timer/Counter2 Output Compare Register Bit 2
282
.equ  OCR2_3  = 3  ; Timer/Counter2 Output Compare Register Bit 3
283
.equ  OCR2_4  = 4  ; Timer/Counter2 Output Compare Register Bit 4
284
.equ  OCR2_5  = 5  ; Timer/Counter2 Output Compare Register Bit 5
285
.equ  OCR2_6  = 6  ; Timer/Counter2 Output Compare Register Bit 6
286
.equ  OCR2_7  = 7  ; Timer/Counter2 Output Compare Register Bit 7
287
288
; ASSR - Asynchronous Status Register
289
.equ  TCR2UB  = 0  ; Timer/counter Control Register2 Update Busy
290
.equ  OCR2UB  = 1  ; Output Compare Register2 Update Busy
291
.equ  TCN2UB  = 2  ; Timer/Counter2 Update Busy
292
.equ  AS2  = 3  ; Asynchronous Timer/counter2
293
294
; SFIOR - Special Function IO Register
295
.equ  PSR2  = 1  ; Prescaler Reset Timer/Counter2
296
297
298
; ***** USART ************************
299
; UDR - USART I/O Data Register
300
.equ  UDR0  = 0  ; USART I/O Data Register bit 0
301
.equ  UDR1  = 1  ; USART I/O Data Register bit 1
302
.equ  UDR2  = 2  ; USART I/O Data Register bit 2
303
.equ  UDR3  = 3  ; USART I/O Data Register bit 3
304
.equ  UDR4  = 4  ; USART I/O Data Register bit 4
305
.equ  UDR5  = 5  ; USART I/O Data Register bit 5
306
.equ  UDR6  = 6  ; USART I/O Data Register bit 6
307
.equ  UDR7  = 7  ; USART I/O Data Register bit 7
308
309
; UCSRA - USART Control and Status Register A
310
.equ  USR  = UCSRA  ; For compatibility
311
.equ  MPCM  = 0  ; Multi-processor Communication Mode
312
.equ  U2X  = 1  ; Double the USART transmission speed
313
.equ  UPE  = 2  ; Parity Error
314
.equ  PE  = UPE  ; For compatibility
315
.equ  DOR  = 3  ; Data overRun
316
.equ  FE  = 4  ; Framing Error
317
.equ  UDRE  = 5  ; USART Data Register Empty
318
.equ  TXC  = 6  ; USART Transmitt Complete
319
.equ  RXC  = 7  ; USART Receive Complete
320
321
; UCSRB - USART Control and Status Register B
322
.equ  UCR  = UCSRB  ; For compatibility
323
.equ  TXB8  = 0  ; Transmit Data Bit 8
324
.equ  RXB8  = 1  ; Receive Data Bit 8
325
.equ  UCSZ2  = 2  ; Character Size
326
.equ  CHR9  = UCSZ2  ; For compatibility
327
.equ  TXEN  = 3  ; Transmitter Enable
328
.equ  RXEN  = 4  ; Receiver Enable
329
.equ  UDRIE  = 5  ; USART Data register Empty Interrupt Enable
330
.equ  TXCIE  = 6  ; TX Complete Interrupt Enable
331
.equ  RXCIE  = 7  ; RX Complete Interrupt Enable
332
333
; UCSRC - USART Control and Status Register C
334
.equ  UCPOL  = 0  ; Clock Polarity
335
.equ  UCSZ0  = 1  ; Character Size
336
.equ  UCSZ1  = 2  ; Character Size
337
.equ  USBS  = 3  ; Stop Bit Select
338
.equ  UPM0  = 4  ; Parity Mode Bit 0
339
.equ  UPM1  = 5  ; Parity Mode Bit 1
340
.equ  UMSEL  = 6  ; USART Mode Select
341
.equ  URSEL  = 7  ; Register Select
342
343
.equ  UBRRHI  = UBRRH  ; For compatibility
344
345
; ***** TWI **************************
346
; TWBR - TWI Bit Rate register
347
.equ  I2BR  = TWBR  ; For compatibility
348
.equ  TWBR0  = 0  ; 
349
.equ  TWBR1  = 1  ; 
350
.equ  TWBR2  = 2  ; 
351
.equ  TWBR3  = 3  ; 
352
.equ  TWBR4  = 4  ; 
353
.equ  TWBR5  = 5  ; 
354
.equ  TWBR6  = 6  ; 
355
.equ  TWBR7  = 7  ; 
356
357
; TWCR - TWI Control Register
358
.equ  I2CR  = TWCR  ; For compatibility
359
.equ  TWIE  = 0  ; TWI Interrupt Enable
360
.equ  I2IE  = TWIE  ; For compatibility
361
.equ  TWEN  = 2  ; TWI Enable Bit
362
.equ  I2EN  = TWEN  ; For compatibility
363
.equ  ENI2C  = TWEN  ; For compatibility
364
.equ  TWWC  = 3  ; TWI Write Collition Flag
365
.equ  I2WC  = TWWC  ; For compatibility
366
.equ  TWSTO  = 4  ; TWI Stop Condition Bit
367
.equ  I2STO  = TWSTO  ; For compatibility
368
.equ  TWSTA  = 5  ; TWI Start Condition Bit
369
.equ  I2STA  = TWSTA  ; For compatibility
370
.equ  TWEA  = 6  ; TWI Enable Acknowledge Bit
371
.equ  I2EA  = TWEA  ; For compatibility
372
.equ  TWINT  = 7  ; TWI Interrupt Flag
373
.equ  I2INT  = TWINT  ; For compatibility
374
375
; TWSR - TWI Status Register
376
.equ  I2SR  = TWSR  ; For compatibility
377
.equ  TWPS0  = 0  ; TWI Prescaler
378
.equ  TWS0  = TWPS0  ; For compatibility
379
.equ  I2GCE  = TWPS0  ; For compatibility
380
.equ  TWPS1  = 1  ; TWI Prescaler
381
.equ  TWS1  = TWPS1  ; For compatibility
382
.equ  TWS3  = 3  ; TWI Status
383
.equ  I2S3  = TWS3  ; For compatibility
384
.equ  TWS4  = 4  ; TWI Status
385
.equ  I2S4  = TWS4  ; For compatibility
386
.equ  TWS5  = 5  ; TWI Status
387
.equ  I2S5  = TWS5  ; For compatibility
388
.equ  TWS6  = 6  ; TWI Status
389
.equ  I2S6  = TWS6  ; For compatibility
390
.equ  TWS7  = 7  ; TWI Status
391
.equ  I2S7  = TWS7  ; For compatibility
392
393
; TWDR - TWI Data register
394
.equ  I2DR  = TWDR  ; For compatibility
395
.equ  TWD0  = 0  ; TWI Data Register Bit 0
396
.equ  TWD1  = 1  ; TWI Data Register Bit 1
397
.equ  TWD2  = 2  ; TWI Data Register Bit 2
398
.equ  TWD3  = 3  ; TWI Data Register Bit 3
399
.equ  TWD4  = 4  ; TWI Data Register Bit 4
400
.equ  TWD5  = 5  ; TWI Data Register Bit 5
401
.equ  TWD6  = 6  ; TWI Data Register Bit 6
402
.equ  TWD7  = 7  ; TWI Data Register Bit 7
403
404
; TWAR - TWI (Slave) Address register
405
.equ  I2AR  = TWAR  ; For compatibility
406
.equ  TWGCE  = 0  ; TWI General Call Recognition Enable Bit
407
.equ  TWA0  = 1  ; TWI (Slave) Address register Bit 0
408
.equ  TWA1  = 2  ; TWI (Slave) Address register Bit 1
409
.equ  TWA2  = 3  ; TWI (Slave) Address register Bit 2
410
.equ  TWA3  = 4  ; TWI (Slave) Address register Bit 3
411
.equ  TWA4  = 5  ; TWI (Slave) Address register Bit 4
412
.equ  TWA5  = 6  ; TWI (Slave) Address register Bit 5
413
.equ  TWA6  = 7  ; TWI (Slave) Address register Bit 6
414
415
416
; ***** WATCHDOG *********************
417
; WDTCR - Watchdog Timer Control Register
418
.equ  WDTCSR  = WDTCR  ; For compatibility
419
.equ  WDP0  = 0  ; Watch Dog Timer Prescaler bit 0
420
.equ  WDP1  = 1  ; Watch Dog Timer Prescaler bit 1
421
.equ  WDP2  = 2  ; Watch Dog Timer Prescaler bit 2
422
.equ  WDE  = 3  ; Watch Dog Enable
423
.equ  WDCE  = 4  ; Watchdog Change Enable
424
.equ  WDTOE  = WDCE  ; For compatibility
425
426
427
; ***** PORTB ************************
428
; PORTB - Port B Data Register
429
.equ  PORTB0  = 0  ; Port B Data Register bit 0
430
.equ  PB0  = 0  ; For compatibility
431
.equ  PORTB1  = 1  ; Port B Data Register bit 1
432
.equ  PB1  = 1  ; For compatibility
433
.equ  PORTB2  = 2  ; Port B Data Register bit 2
434
.equ  PB2  = 2  ; For compatibility
435
.equ  PORTB3  = 3  ; Port B Data Register bit 3
436
.equ  PB3  = 3  ; For compatibility
437
.equ  PORTB4  = 4  ; Port B Data Register bit 4
438
.equ  PB4  = 4  ; For compatibility
439
.equ  PORTB5  = 5  ; Port B Data Register bit 5
440
.equ  PB5  = 5  ; For compatibility
441
.equ  PORTB6  = 6  ; Port B Data Register bit 6
442
.equ  PB6  = 6  ; For compatibility
443
.equ  PORTB7  = 7  ; Port B Data Register bit 7
444
.equ  PB7  = 7  ; For compatibility
445
446
; DDRB - Port B Data Direction Register
447
.equ  DDB0  = 0  ; Port B Data Direction Register bit 0
448
.equ  DDB1  = 1  ; Port B Data Direction Register bit 1
449
.equ  DDB2  = 2  ; Port B Data Direction Register bit 2
450
.equ  DDB3  = 3  ; Port B Data Direction Register bit 3
451
.equ  DDB4  = 4  ; Port B Data Direction Register bit 4
452
.equ  DDB5  = 5  ; Port B Data Direction Register bit 5
453
.equ  DDB6  = 6  ; Port B Data Direction Register bit 6
454
.equ  DDB7  = 7  ; Port B Data Direction Register bit 7
455
456
; PINB - Port B Input Pins
457
.equ  PINB0  = 0  ; Port B Input Pins bit 0
458
.equ  PINB1  = 1  ; Port B Input Pins bit 1
459
.equ  PINB2  = 2  ; Port B Input Pins bit 2
460
.equ  PINB3  = 3  ; Port B Input Pins bit 3
461
.equ  PINB4  = 4  ; Port B Input Pins bit 4
462
.equ  PINB5  = 5  ; Port B Input Pins bit 5
463
.equ  PINB6  = 6  ; Port B Input Pins bit 6
464
.equ  PINB7  = 7  ; Port B Input Pins bit 7
465
466
467
; ***** PORTC ************************
468
; PORTC - Port C Data Register
469
.equ  PORTC0  = 0  ; Port C Data Register bit 0
470
.equ  PC0  = 0  ; For compatibility
471
.equ  PORTC1  = 1  ; Port C Data Register bit 1
472
.equ  PC1  = 1  ; For compatibility
473
.equ  PORTC2  = 2  ; Port C Data Register bit 2
474
.equ  PC2  = 2  ; For compatibility
475
.equ  PORTC3  = 3  ; Port C Data Register bit 3
476
.equ  PC3  = 3  ; For compatibility
477
.equ  PORTC4  = 4  ; Port C Data Register bit 4
478
.equ  PC4  = 4  ; For compatibility
479
.equ  PORTC5  = 5  ; Port C Data Register bit 5
480
.equ  PC5  = 5  ; For compatibility
481
.equ  PORTC6  = 6  ; Port C Data Register bit 6
482
.equ  PC6  = 6  ; For compatibility
483
484
; DDRC - Port C Data Direction Register
485
.equ  DDC0  = 0  ; Port C Data Direction Register bit 0
486
.equ  DDC1  = 1  ; Port C Data Direction Register bit 1
487
.equ  DDC2  = 2  ; Port C Data Direction Register bit 2
488
.equ  DDC3  = 3  ; Port C Data Direction Register bit 3
489
.equ  DDC4  = 4  ; Port C Data Direction Register bit 4
490
.equ  DDC5  = 5  ; Port C Data Direction Register bit 5
491
.equ  DDC6  = 6  ; Port C Data Direction Register bit 6
492
493
; PINC - Port C Input Pins
494
.equ  PINC0  = 0  ; Port C Input Pins bit 0
495
.equ  PINC1  = 1  ; Port C Input Pins bit 1
496
.equ  PINC2  = 2  ; Port C Input Pins bit 2
497
.equ  PINC3  = 3  ; Port C Input Pins bit 3
498
.equ  PINC4  = 4  ; Port C Input Pins bit 4
499
.equ  PINC5  = 5  ; Port C Input Pins bit 5
500
.equ  PINC6  = 6  ; Port C Input Pins bit 6
501
502
503
; ***** PORTD ************************
504
; PORTD - Port D Data Register
505
.equ  PORTD0  = 0  ; Port D Data Register bit 0
506
.equ  PD0  = 0  ; For compatibility
507
.equ  PORTD1  = 1  ; Port D Data Register bit 1
508
.equ  PD1  = 1  ; For compatibility
509
.equ  PORTD2  = 2  ; Port D Data Register bit 2
510
.equ  PD2  = 2  ; For compatibility
511
.equ  PORTD3  = 3  ; Port D Data Register bit 3
512
.equ  PD3  = 3  ; For compatibility
513
.equ  PORTD4  = 4  ; Port D Data Register bit 4
514
.equ  PD4  = 4  ; For compatibility
515
.equ  PORTD5  = 5  ; Port D Data Register bit 5
516
.equ  PD5  = 5  ; For compatibility
517
.equ  PORTD6  = 6  ; Port D Data Register bit 6
518
.equ  PD6  = 6  ; For compatibility
519
.equ  PORTD7  = 7  ; Port D Data Register bit 7
520
.equ  PD7  = 7  ; For compatibility
521
522
; DDRD - Port D Data Direction Register
523
.equ  DDD0  = 0  ; Port D Data Direction Register bit 0
524
.equ  DDD1  = 1  ; Port D Data Direction Register bit 1
525
.equ  DDD2  = 2  ; Port D Data Direction Register bit 2
526
.equ  DDD3  = 3  ; Port D Data Direction Register bit 3
527
.equ  DDD4  = 4  ; Port D Data Direction Register bit 4
528
.equ  DDD5  = 5  ; Port D Data Direction Register bit 5
529
.equ  DDD6  = 6  ; Port D Data Direction Register bit 6
530
.equ  DDD7  = 7  ; Port D Data Direction Register bit 7
531
532
; PIND - Port D Input Pins
533
.equ  PIND0  = 0  ; Port D Input Pins bit 0
534
.equ  PIND1  = 1  ; Port D Input Pins bit 1
535
.equ  PIND2  = 2  ; Port D Input Pins bit 2
536
.equ  PIND3  = 3  ; Port D Input Pins bit 3
537
.equ  PIND4  = 4  ; Port D Input Pins bit 4
538
.equ  PIND5  = 5  ; Port D Input Pins bit 5
539
.equ  PIND6  = 6  ; Port D Input Pins bit 6
540
.equ  PIND7  = 7  ; Port D Input Pins bit 7
541
542
543
; ***** EEPROM ***********************
544
; EEDR - EEPROM Data Register
545
.equ  EEDR0  = 0  ; EEPROM Data Register bit 0
546
.equ  EEDR1  = 1  ; EEPROM Data Register bit 1
547
.equ  EEDR2  = 2  ; EEPROM Data Register bit 2
548
.equ  EEDR3  = 3  ; EEPROM Data Register bit 3
549
.equ  EEDR4  = 4  ; EEPROM Data Register bit 4
550
.equ  EEDR5  = 5  ; EEPROM Data Register bit 5
551
.equ  EEDR6  = 6  ; EEPROM Data Register bit 6
552
.equ  EEDR7  = 7  ; EEPROM Data Register bit 7
553
554
; EECR - EEPROM Control Register
555
.equ  EERE  = 0  ; EEPROM Read Enable
556
.equ  EEWE  = 1  ; EEPROM Write Enable
557
.equ  EEMWE  = 2  ; EEPROM Master Write Enable
558
.equ  EEWEE  = EEMWE  ; For compatibility
559
.equ  EERIE  = 3  ; EEPROM Ready Interrupt Enable
560
561
562
; ***** CPU **************************
563
; SREG - Status Register
564
.equ  SREG_C  = 0  ; Carry Flag
565
.equ  SREG_Z  = 1  ; Zero Flag
566
.equ  SREG_N  = 2  ; Negative Flag
567
.equ  SREG_V  = 3  ; Two's Complement Overflow Flag
568
.equ  SREG_S  = 4  ; Sign Bit
569
.equ  SREG_H  = 5  ; Half Carry Flag
570
.equ  SREG_T  = 6  ; Bit Copy Storage
571
.equ  SREG_I  = 7  ; Global Interrupt Enable
572
573
; MCUCR - MCU Control Register
574
;.equ  ISC00  = 0  ; Interrupt Sense Control 0 Bit 0
575
;.equ  ISC01  = 1  ; Interrupt Sense Control 0 Bit 1
576
;.equ  ISC10  = 2  ; Interrupt Sense Control 1 Bit 0
577
;.equ  ISC11  = 3  ; Interrupt Sense Control 1 Bit 1
578
.equ  SM0  = 4  ; Sleep Mode Select
579
.equ  SM1  = 5  ; Sleep Mode Select
580
.equ  SM2  = 6  ; Sleep Mode Select
581
.equ  SE  = 7  ; Sleep Enable
582
583
; MCUCSR - MCU Control And Status Register
584
.equ  MCUSR  = MCUCSR  ; For compatibility
585
.equ  PORF  = 0  ; Power-on reset flag
586
.equ  EXTRF  = 1  ; External Reset Flag
587
.equ  BORF  = 2  ; Brown-out Reset Flag
588
.equ  WDRF  = 3  ; Watchdog Reset Flag
589
590
; OSCCAL - Oscillator Calibration Value
591
.equ  CAL0  = 0  ; Oscillator Calibration Value Bit0
592
.equ  CAL1  = 1  ; Oscillator Calibration Value Bit1
593
.equ  CAL2  = 2  ; Oscillator Calibration Value Bit2
594
.equ  CAL3  = 3  ; Oscillator Calibration Value Bit3
595
.equ  CAL4  = 4  ; Oscillator Calibration Value Bit4
596
.equ  CAL5  = 5  ; Oscillator Calibration Value Bit5
597
.equ  CAL6  = 6  ; Oscillator Calibration Value Bit6
598
.equ  CAL7  = 7  ; Oscillator Calibration Value Bit7
599
600
; SPMCR - Store Program Memory Control Register
601
.equ  SPMEN  = 0  ; Store Program Memory Enable
602
.equ  PGERS  = 1  ; Page Erase
603
.equ  PGWRT  = 2  ; Page Write
604
.equ  BLBSET  = 3  ; Boot Lock Bit Set
605
.equ  RWWSRE  = 4  ; Read-While-Write Section Read Enable
606
.equ  RWWSB  = 6  ; Read-While-Write Section Busy
607
.equ  SPMIE  = 7  ; SPM Interrupt Enable
608
609
; SFIOR - Special Function IO Register
610
.equ  PSR10  = 0  ; Prescaler Reset Timer/Counter1 and Timer/Counter0
611
.equ  PUD  = 2  ; Pull-up Disable
612
.equ  ADHSM  = 4  ; ADC High Speed Mode
613
614
615
; ***** AD_CONVERTER *****************
616
; ADMUX - The ADC multiplexer Selection Register
617
.equ  MUX0  = 0  ; Analog Channel and Gain Selection Bits
618
.equ  MUX1  = 1  ; Analog Channel and Gain Selection Bits
619
.equ  MUX2  = 2  ; Analog Channel and Gain Selection Bits
620
.equ  MUX3  = 3  ; Analog Channel and Gain Selection Bits
621
.equ  ADLAR  = 5  ; Left Adjust Result
622
.equ  REFS0  = 6  ; Reference Selection Bit 0
623
.equ  REFS1  = 7  ; Reference Selection Bit 1
624
625
; ADCSRA - The ADC Control and Status register
626
.equ  ADCSR  = ADCSRA  ; For compatibility
627
.equ  ADPS0  = 0  ; ADC  Prescaler Select Bits
628
.equ  ADPS1  = 1  ; ADC  Prescaler Select Bits
629
.equ  ADPS2  = 2  ; ADC  Prescaler Select Bits
630
.equ  ADIE  = 3  ; ADC Interrupt Enable
631
.equ  ADIF  = 4  ; ADC Interrupt Flag
632
.equ  ADFR  = 5  ; ADC  Free Running Select
633
.equ  ADSC  = 6  ; ADC Start Conversion
634
.equ  ADEN  = 7  ; ADC Enable
635
636
637
638
; ***** LOCKSBITS ********************************************************
639
.equ  LB1  = 0  ; Lock bit
640
.equ  LB2  = 1  ; Lock bit
641
.equ  BLB01  = 2  ; Boot Lock bit
642
.equ  BLB02  = 3  ; Boot Lock bit
643
.equ  BLB11  = 4  ; Boot lock bit
644
.equ  BLB12  = 5  ; Boot lock bit
645
646
647
; ***** FUSES ************************************************************
648
; LOW fuse bits
649
.equ  CKSEL0  = 0  ; Select Clock Source
650
.equ  CKSEL1  = 1  ; Select Clock Source
651
.equ  CKSEL2  = 2  ; Select Clock Source
652
.equ  CKSEL3  = 3  ; Select Clock Source
653
.equ  SUT0  = 4  ; Select start-up time
654
.equ  SUT1  = 5  ; Select start-up time
655
.equ  BODEN  = 6  ; Brown out detector enable
656
.equ  BODLEVEL  = 7  ; Brown out detector trigger level
657
658
; HIGH fuse bits
659
.equ  BOOTRST  = 0  ; Select Reset Vector
660
.equ  BOOTSZ0  = 1  ; Select Boot Size
661
.equ  BOOTSZ1  = 2  ; Select Boot Size
662
.equ  EESAVE  = 3  ; EEPROM memory is preserved through chip erase
663
.equ  CKOPT  = 4  ; Oscillator Options
664
.equ  SPIEN  = 5  ; Enable Serial programming and Data Downloading
665
.equ  WTDON  = 6  ; Enable watchdog
666
.equ  RSTDISBL  = 7  ; Disable reset
667
668
669
670
; ***** CPU REGISTER DEFINITIONS *****************************************
671
.def  XH  = r27
672
.def  XL  = r26
673
.def  YH  = r29
674
.def  YL  = r28
675
.def  ZH  = r31
676
.def  ZL  = r30
677
678
679
680
; ***** DATA MEMORY DECLARATIONS *****************************************
681
.equ  FLASHEND  = 0x0fff  ; Note: Word address
682
.equ  IOEND  = 0x003f
683
.equ  SRAM_START  = 0x0060
684
.equ  SRAM_SIZE  = 1024
685
.equ  RAMEND  = 0x045f
686
.equ  XRAMEND  = 0x0000
687
.equ  E2END  = 0x01ff
688
.equ  EEPROMEND  = 0x01ff
689
.equ  EEADRBITS  = 9
690
#pragma AVRPART MEMORY PROG_FLASH 8192
691
#pragma AVRPART MEMORY EEPROM 512
692
#pragma AVRPART MEMORY INT_SRAM SIZE 1024
693
#pragma AVRPART MEMORY INT_SRAM START_ADDR 0x60
694
695
696
697
; ***** BOOTLOADER DECLARATIONS ******************************************
698
.equ  NRWW_START_ADDR  = 0xc00
699
.equ  NRWW_STOP_ADDR  = 0xfff
700
.equ  RWW_START_ADDR  = 0x0
701
.equ  RWW_STOP_ADDR  = 0xbff
702
.equ  PAGESIZE  = 32
703
.equ  FIRSTBOOTSTART  = 0xf80
704
.equ  SECONDBOOTSTART  = 0xf00
705
.equ  THIRDBOOTSTART  = 0xe00
706
.equ  FOURTHBOOTSTART  = 0xc00
707
.equ  SMALLBOOTSTART  = FIRSTBOOTSTART
708
.equ  LARGEBOOTSTART  = FOURTHBOOTSTART
709
710
711
712
; ***** INTERRUPT VECTORS ************************************************
713
.equ  INT0addr  = 0x0001  ; External Interrupt Request 0
714
.equ  INT1addr  = 0x0002  ; External Interrupt Request 1
715
.equ  OC2addr  = 0x0003  ; Timer/Counter2 Compare Match
716
.equ  OVF2addr  = 0x0004  ; Timer/Counter2 Overflow
717
.equ  ICP1addr  = 0x0005  ; Timer/Counter1 Capture Event
718
.equ  OC1Aaddr  = 0x0006  ; Timer/Counter1 Compare Match A
719
.equ  OC1Baddr  = 0x0007  ; Timer/Counter1 Compare Match B
720
.equ  OVF1addr  = 0x0008  ; Timer/Counter1 Overflow
721
.equ  OVF0addr  = 0x0009  ; Timer/Counter0 Overflow
722
.equ  SPIaddr  = 0x000a  ; Serial Transfer Complete
723
.equ  URXCaddr  = 0x000b  ; USART, Rx Complete
724
.equ  UDREaddr  = 0x000c  ; USART Data Register Empty
725
.equ  UTXCaddr  = 0x000d  ; USART, Tx Complete
726
.equ  ADCCaddr  = 0x000e  ; ADC Conversion Complete
727
.equ  ERDYaddr  = 0x000f  ; EEPROM Ready
728
.equ  ACIaddr  = 0x0010  ; Analog Comparator
729
.equ  TWIaddr  = 0x0011  ; 2-wire Serial Interface
730
.equ  SPMRaddr  = 0x0012  ; Store Program Memory Ready
731
732
.equ  INT_VECTORS_SIZE  = 19  ; size in words
733
734
#pragma AVRPART CORE INSTRUCTIONS_NOT_SUPPORTED break
735
736
#endif  /* _M8DEF_INC_ */
737
738
; ***** END OF FILE ******************************************************
Ich hoffe es kann mir jemand helfen. Kann leider keine 
Assemblerprogrammierung und C nur für den Hausgebrauch mit Arduino.

Grüße

Andre

von Karl H. (kbuchegg)


Lesenswert?

Andre Meschke schrieb:

> Ich hoffe es kann mir jemand helfen. Kann leider keine
> Assemblerprogrammierung und C nur für den Hausgebrauch mit Arduino.

Aha. Und du glaubst das ist besser?

Wieso räumst du den C Code nicht einfach auf? Soooo schlecht ist der 
auch wieder nicht. Mit etwas drüber polieren könnte der ganz gut werden. 
Als erstes mal alles rauswerfen, was offenbar keine Funktion erfüllt. 
Dazu gehört die Kalibiermöglichkeit im Code und alles was damit 
zusammenhängt. Dann alles was auskommentiert ist - das verwirrt auf 
lange Sicht nur. Da ist dann schon ein guter Teil des Codes weggefallen. 
Und den Rest kann man analysieren, wie das zusammenhängt. Der ADC wird 
offenbar zur Überwachung eingesetzt. Wenn man das im Hinterkopf behält, 
dann kann man den auch erst mal rauswerfen. Dann bleibt schon nicht mehr 
viel übrig. Gerade mal die Logik um den Servopuls auszuwerten und daraus 
abgeleitet die Motor-PWM anzusteuern. Da ist dann noch eine 
Expo-Umrechung drinnen. Brauchst du die? Wenn nein, dann fliegt sie auch 
gleich mal raus. Die Motor-PWM Genererierung sollte dann nun wirklich 
nicht schwer zu verstehen bzw. zu modifizieren bzw. an deine 
Vorstellungen anzupassen sein. Dann sieht man sich an, ob man die 
Motorstromüberwachung noch haben will, dazu kommt dann der ADC wieder 
rein und gut ists. So schwer ist das auch wieder nicht bei einem 
Brushless-Motor. Im Prinzip ist das die Auswertung des Kanal-Pulses, der 
die Knüppelstellung wiederspiegelt und davon abgeleitet bzw. umgerechnet 
die Erzeugung einer PWM, welche die Fahrspannung steuert. Das ist nicht 
viel mehr als dein Dreisatz. Recht viel mehr braucht man dazu erst mal 
nicht. Der Softanlauf, damit die Motorspannung nicht schlagartig hoch 
bzw. runter geht ist nett und schont die Mechanik - und ist genauso 
simpel realisiert. Das ist ja grundsätzlich im vorliegenden Code alles 
in Ordnung. Er ist nur sehr unübersichtlich.

Auch mit Hausgebrauch Arduino kann man durchaus einen Motorregeler 
selbst programmieren, wenn man eine Vorlage hat, von der man sich 
abschauen kann, wie die einzelnen Teile beispielsweise gemacht werden.

Das ist sinnvoller als tagelang zu versuchen fremden Code in einzelnen 
Details an seine Wünsche anzupassen bzw. sich immer wieder neuen Code zu 
suchen, den man nicht versteht und der dann doch nicht die Stückeln 
spielt, die man haben will. Gerade in der Arduino Welt wird einem so 
etwas nun wirklich nicht schwer gemacht. Trau dich! Wenn du vor 
Weihnachten angefangen hättest, wärst du schon längst fertig und du 
würdest jedes einzelne Detail deines Reglers verstehen.

: Bearbeitet durch User
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.