#include "units/seg7.hpp"
#include "units/poti.hpp"
#include "units/encoder.hpp"
+#include "units/r2r.hpp"
+#include "units/motor.hpp"
extern "C" {
void __cxa_pure_virtual () {
Seg7 seg7;
Poti poti;
Encoder encoder;
+ R2r r2r;
+ Motor motor;
}
// Nano-644 LEDs (Green, Orange, Red)
DDRC |= (1 << DDC4) | (1 << DDC3) | (1 << DDC2);
PORTC &= ~((1 << PORT4) | (1 << PORT3) | (1 << PORT2));
-
+
// Nano-644 push button SW2
DDRC &= ~(1 << DDC5);
PORTC |= (1 << PORT5); // enable internal pullup resistor
printf("======================================");
- TestUnit *unit[] = { &led, &sw, &rgb, &seg7, &poti, &encoder };
+ TestUnit *unit[] = { &motor, &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r };
for (uint8_t i = 0; i < sizeof(unit) / sizeof(unit[0]); i++) {
TestUnit *pu = unit[i];
static uint16_t timer500ms = 0;
static uint8_t timer100us = 0;
+ if (encoder.enabled) {
+ encoder.tick100us();
+ }
+ if (motor.enabled) {
+ motor.tick100us();
+ }
+
timer100us++;
- encoder.tick100us();
if (timer100us >= 10) {
timer100us = 0;
if (timer1ms > 0) {
void Encoder::cleanup () {
DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0));
PORTB &= ~((1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0));
+ enabled = 0;
}
int8_t Encoder::run (uint8_t subtest) {
printf("init");
DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0));
PORTB |= (1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0); // enable pullup
+ enabled = 1;
return 0;
}
};
void Encoder::tick100us () {
- static EncoderState lastState = { 1, 1 };;
+ static EncoderState lastState = { 1, 1 };
static EncoderState lastStableState = { 1, 1 };
if ((DDRB & 0x03) || (PORTB & 0x07) != 0x07) {
class Encoder : public TestUnit {
public:
+ uint8_t enabled;
int8_t count;
public:
- Encoder () { reset(); };
+ Encoder () { reset(); enabled = 0; };
virtual void cleanup ();
virtual int8_t run (uint8_t subtest);
virtual const char *getName () { return "Encoder"; }
-#include "led.hpp"
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
+#include "led.hpp"
#include "../main.hpp"
void Led::cleanup () {
--- /dev/null
+#include <stdio.h>
+#include <avr/io.h>
+#include <util/atomic.h>
+
+#include "motor.hpp"
+#include "../main.hpp"
+
+void Motor::cleanup () {
+ ADMUX = 0;
+ ADCSRA = 0;
+ TCCR0A = 0;
+ TCCR0B = 0;
+ DDRB &= ~((1 << PB4) | (1 << PB3));
+ PORTA &= ~(1 << PORTA3);
+ enabled = 0;
+}
+
+int8_t Motor::run (uint8_t subtest) {
+ switch (subtest) {
+ case 0: {
+ printf("init");
+ ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V
+ ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
+ TCCR0A = (1 << COM0A1) | (1 << WGM01) | (1 << WGM00); // Fast PWM on OC0A
+ // TCCR0B = (1 << CS02) | ( 1 << CS00); // f = 12 MHz / 1024 = 11,71875 kHz -> fPWM=45Hz
+ TCCR0B = (1 << CS02); // f = 12 MHz / 256 = 46,875 kHz -> fPWM=183,1Hz
+ DDRB |= (1 << PB4) | (1 << PB3); // Motor enable
+ PORTA |= (1 << PORTA3); // push button for Motor enable control
+ enabled = 1;
+ return 0;
+ }
+
+ case 1: {
+ printf("\n");
+ while (wait(10) == EOF) {
+
+ ADCSRA |= (1 << ADSC); // start ADC
+ while (ADCSRA & (1 << ADSC)) {} // wait for result
+ printf("\r => ADC0=%3d", ADCH);
+
+ ADMUX = (1 << ADLAR) | (1 << REFS1) | (1 << REFS0) | 2; // ADC2, VREF=2.5V
+
+ uint8_t dutyCycle = 0xff - ADCH;
+ if (dutyCycle <= 1) {
+ dutyCycle = 0;
+ } else if (dutyCycle > 254) {
+ dutyCycle = 255;
+ }
+ OCR0A = dutyCycle;
+ printf(" PWM/OC0A=%3d", dutyCycle);
+
+ ADCSRA |= (1 << ADSC); // start ADC
+ while (ADCSRA & (1 << ADSC)) {} // wait for result
+ printf(" ADC2=%3d", ADCH);
+ ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V
+
+ if ((PINA & (1<< PA3)) == 0) {
+ PORTB &= ~(1 << PORTB4);
+ } else {
+ PORTB |= (1 << PORTB4);
+ }
+
+ uint16_t timer;
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ timer = rpmTimer;
+ }
+ float rpm = 60.0 / (float)timer / 0.0001;
+ if (timer > 0) {
+ printf(" n= %4d U/min", (int)rpm);
+ } else {
+ printf(" no rotation");
+ }
+
+ }
+ return 0;
+ }
+
+ case 2: {
+ printf("\r => end");
+ break;
+ }
+ }
+
+ return -1;
+}
+
+void Motor::tick100us () {
+ static uint16_t timerH = 0;
+ static uint16_t timerL = 0;
+ static uint8_t pinb = 0;
+ if ((PINB & 0x01) && PINB != pinb && timerL > 10) {
+ rpmTimer = timerL + timerH;
+ timerL = 0;
+ timerH = 0;
+ }
+ if (PINB & 0x01) {
+ timerH = timerH < 0x4000 ? timerH + 1 : 0x4000;
+ } else {
+ timerL = timerL < 0x4000 ? timerL + 1 : 0x4000;
+ }
+ if (timerH >= 0x4000 || timerL >= 0x4000) {
+ rpmTimer = 0; // no ratation detected
+ }
+ pinb = PINB;
+}
+
+
--- /dev/null
+#ifndef MOTOR_HPP
+#define MOTOR_HPP
+
+#include <stdint.h>
+#include "../main.hpp"
+
+class Motor : public TestUnit {
+ public:
+ uint8_t enabled;
+ uint16_t rpmTimer;
+
+ public:
+ Motor () { enabled = 0; rpmTimer = 0; };
+ virtual void cleanup ();
+ virtual int8_t run (uint8_t subtest);
+ virtual const char *getName () { return "Motor"; }
+ void tick100us ();
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include <stdio.h>
+#include <avr/io.h>
+
+#include "r2r.hpp"
+#include "../main.hpp"
+
+void R2r::cleanup () {
+ ADMUX = 0;
+ ADCSRA = 0;
+}
+
+int8_t R2r::run (uint8_t subtest) {
+ switch (subtest) {
+ case 0: {
+ printf("init");
+ ADMUX = (1 << REFS0) | 2; // ADC2, VREF=AVCC=3.3V
+ ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
+ return 0;
+ }
+
+ case 1: {
+ printf("\n");
+ while (wait(10) == EOF) {
+ printf("\r => Measure ADC2: ");
+ ADCSRA |= (1 << ADSC); // start ADC
+ while (ADCSRA & (1 << ADSC)) {} // wait for result
+ printf("%4d (0x%03x)", ADC, ADC);
+ uint8_t sw = (ADC + 32) / 64;
+ printf(" SW9:6 = %d %d% d %d ", sw >> 3, (sw >> 2) & 0x01, (sw >> 1) & 0x01, sw & 0x01 );
+ }
+ return 0;
+ }
+
+ case 2: {
+ printf("\r => R2R end%20s", " ");
+ break;
+ }
+ }
+
+ return -1;
+}
+
+
--- /dev/null
+#ifndef R2R_HPP
+#define R2R_PP
+
+#include <stdint.h>
+#include "../main.hpp"
+
+class R2r : public TestUnit {
+ public:
+ R2r () {};
+ virtual void cleanup ();
+ virtual int8_t run (uint8_t subtest);
+ virtual const char *getName () { return "R2R"; }
+};
+
+#endif
\ No newline at end of file