Mag sein, dass dieser Thread jetzt schon ein wenig OFF-TOPIC ist, aber weil es noch die NiboRoboLib 3.4.1 betrifft und eben den NIBOburger.. mit 1284p und 15MHz
Obwohl die unterschiedliche Bandgap Spannungen von ATmega16 und ATmega1284 in der analog.c berücksichtigt werden - die Spannungsanzeige mit GetMillivolt() liegt beim ATmega1284 mit 15MHz weit daneben..
Nach dem Studium der Theorie (z.Bsp. Atmel Appnote AVR353* und anderer "Versorgungsspannung mithilfe Bandgap ermitteln"-Artikeln), habe ich jetzt zwei Sachen verschlimmbessert (*wäre auch ein cooles Lib Feature gewesen, wenn auch die Temperatur abgefragt werden könnte).
Das Umschalten der Referenzspannung (am Pin AREF) zwischen der internen Referenzspannung (2,56V) und VCC (ca.4,8V) braucht einige Zeit, bis sich Kapazitäten an die neue Spannung AREF "gewöhnt" haben. Nach dem Umschalten von AREF sollten erst einige Dummy-Messungen gemacht werden (ist in der analog.c nicht erkennbar).
1. Versuch: Kondensator C2 10nF weiter verringern - bei mir isser jetzt ausgelötet; das hat aber keine Änderung gebracht, und die anderen Analogwerte sind auch ohne C2 i.O. (oder besser normal).
2. Versuch: In der analog.c die Stelle mit dem Timing für die ADC Ansteuerung verändert (eigentlich ohne genau zu wissen was da gemacht wird -für was steht STD?).
/*
// Original Code aus der NiboRoboLib 3.4 auskommentiert
#if F_CPU==15000000
#define STD0 0
#define STD2 2
#define STD3 3
#define STD4 4
#define STD5 5
#define STD6 6
#elif F_CPU==20000000
#define STD0 0
#define STD2 3
#define STD3 4
#define STD4 5
#define STD5 7
#define STD6 8
#else
#error "unsupported clock speed!"
#endif
*/
// Timing für 20MHz aktiviert
#define STD0 0
#define STD2 3
#define STD3 4
#define STD4 5
#define STD5 7
#define STD6 8
Die Bibliotheken mit dem WinAVR und das Projekt im Studio komplett neu gebaut.
Ergebnis - die Spannung wird jetzt etwas genauer (350mV mehr) und nibo_checkMonitorVoltage() kann wieder verwendet werden.
Können da eigentlich noch höhere Werte verwendet werden?
Meine Empfehlung daher, für die nächste Lib-Version das Timing der ADC nach dem Umschalten von AREF mehr verzögern.
..und noch etwas in der analog.c (nur so zur Info - der ADC soll mit 50..200kHz getaktet werden):
nibo_initialization |= NIBO_ANALOG_INITIALIZED;
ADCSRA = _BV(ADPS2) // prescale faktor = 128 ADC laeuft
| _BV(ADPS1) // mit 15 MHz / 128 = 120 kHz
| _BV(ADPS0) // oder mit 20MHz / 128 = 160kHz <------ ;)
| _BV(ADEN) // ADC an
// | _BV(ADATE) // auto trigger
| _BV(ADIE) // enable interrupt
| _BV(ADSC); // Beginne mit der Konvertierung
Und noch ein Thema -
Nach einem resetOdometry funktioniert das setTarget nicht mehr, weil das Ziel ja schon/noch erreicht sein soll
in der odometry.c sind zwei Variablen mit "obsolete" kommentiert, und die werden auch nicht initialisiert oder resettet..
volatile int8_t odometry_pid_left; // obsolete
volatile int8_t odometry_pid_right; // obsolete
volatile int16_t odometry_left;
volatile int16_t odometry_right;
int16_t odometry_usr_left;
int16_t odometry_usr_right;
void odometry_init() {
// enable int0 and int1 on rising edge
#ifndef GICR
// ATmega644
EICRA |= _BV(ISC11) | _BV(ISC10) | _BV(ISC01) | _BV(ISC00);
EIMSK |= _BV(INT1) | _BV(INT0);
#else
// ATmega16
MCUCR |= _BV(ISC11) | _BV(ISC10) | _BV(ISC01) | _BV(ISC00);
GICR |= _BV(INT1) | _BV(INT0);
#endif
set_output_groupbitval(IO_MOTOR, DIR_LEFT, 0);
set_output_groupbitval(IO_MOTOR, DIR_RIGHT, 1);
}
void odometry_reset() {
ATOMIC_C90_BEGIN()
odometry_usr_left = odometry_left;
odometry_usr_right = odometry_right;
ATOMIC_C90_END()
}
:
:
ISR(INT0_vect) {
if (get_output_groupbit(IO_MOTOR, DIR_LEFT)) odometry_pid_left--, odometry_left--; else odometry_pid_left++, odometry_left++;
}
ISR(INT1_vect) {
if (get_output_groupbit(IO_MOTOR, DIR_RIGHT)) odometry_pid_right++, odometry_right++; else odometry_pid_right--, odometry_right--;
}
in der motpid.c tauchen diese "obsoleten" Variablen aber auch wieder auf
extern volatile int8_t odometry_pid_left;
extern volatile int8_t odometry_pid_right;
extern volatile int16_t odometry_left;
extern volatile int16_t odometry_right;
:
:
void motpid_left_timer_int(void) {
motpid_left_speed = (3*motpid_left_speed + (MOTPID_FREQ/2)*odometry_pid_left)/4;
:
:
odometry_pid_left = 0;
}
Müssen odometry_pid_left und ~right eventuell in odometry_reset() auch auf 0 gesetzt werden, damit man nach dem reset wieder ein absolutes Target angeben kann?