Hallo Wissende,
Für kleine Steuerungsaufgaben verwende ich gerne den Arduino Nano. Da das allerdings nur mit längeren Pausen stattfindet, fange ich leider immer wieder von Neuem an ;-(
Diesmal hätte ich eine Aufgabe zu Frequenzvervielfachung im Bereich von wenigen Hertz bis zu ca. 200Hz. Ein passendes Programm habe Dank des Fleißes Anderer schon gefunden und erfolgreich getestet.
Diese Programm verwendet zur Deklaration der Frequenzvervielfachung einen "enum" Wert.
enum { MULTIPLIER = 6 }; // Zahlenwert ist der halbe Vervielfacher, den ich gerne als Variable hätte, durch externe Schalter, einstellbar,
Das ist mir leider bisher nicht gelungen, weil ich offenbar die Funktion nicht richtig verstehe.
Die Multiplier-Funktion läuft in einer Interrupt-Routine ab, im Loop wird der Prozessor schlafen geschickt und wacht mit dem nächsten Eingangsimpuls wieder auf.
Hier der von mir bereits veränderte Code:
// Name: FrequencyMultiplier.ino
// Date: 2016-11-29
// Uses: Digitla frequency multiplier example.
// Author: Andrew Que (http://www.DrQue.net)
//
// (C) Copyright 2016 by Andrew Que
// http://www.bb7.com/
//=================================================================================================
#include <avr/sleep.h>
// Pin for multiplied output.
// NOTE: Fixed to the output for OCR1A.
enum { OUTPUT_PIN = 9 };
// Pin for input frequency.
// NOTE: Fixed to the input capture pin.
enum { INPUT_PIN = 8 };
// How many divisions to break the rotation into.
// This is basically the multiplication factor for the incoming frequency.
enum { MULTIPLIER = 6 };
/ /int MULTIPLIER = 8 ; Versuch - nicht gelungen ...
// Timer count when the most recent input pulse arrived.
static unsigned volatile currentTime;
// Timer count when the previous input pulse arrived.
static unsigned volatile lastTime;
// Width of the incoming input pulse (in timer counts).
static unsigned volatile inputPulseWidth;
// Period of a sub-division of the input pulse.
static unsigned volatile divisionPeriod;
// Current subdivision.
static unsigned volatile divisionCount = 0;
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// variables will change:
int buttonState = 0; // variable for reading the pushbutton status
//-------------------------------------------------------------------------------------------------
// USES:
// Interrupt for timer 1 compare A. Used to set new compare value to toggle output pin.
//-------------------------------------------------------------------------------------------------
ISR( TIMER1_COMPA_vect )
{
// Lag factor. Used to correct phase once each rotation. Typically zero.
int lag = 0;
// Count this division.
divisionCount += 1;
// If half way through the cycle calculate a correction factor for phase.
if ( ( MULTIPLIER / 2 ) == divisionCount )
lag = OCR1A - ( currentTime + ( inputPulseWidth / 2 ) );
// Rollover at pulse count.
if ( MULTIPLIER == divisionCount )
divisionCount = 0;
// Set new next compare value.
OCR1A += ( divisionPeriod / 2 ) - lag;
}
//-------------------------------------------------------------------------------------------------
// USES:
// Interrupt for timer 1 capture event. Used to measure the width of the input pin
// pulse and calculate the division period.
//-------------------------------------------------------------------------------------------------
ISR( TIMER1_CAPT_vect )
{
// Disable interrupts.
cli();
// Grab input capture.
// This is the time at which the input pulse had a rising edge.
currentTime = ICR1;
// Measure the time between this pulse and the previous pulse.
inputPulseWidth = currentTime - lastTime;
// Make the last time the current time for next measurement.
lastTime = currentTime;
// Calculate period of divisions.
// Include long and short divisions.
divisionPeriod = inputPulseWidth / ( MULTIPLIER / 2);
// Enable compare output.
TCCR1A |= 1 << COM1A0;
// Enable interrupts.
sei();
}
//-------------------------------------------------------------------------------------------------
// USES:
// Setup I/O and timers for operation.
//-------------------------------------------------------------------------------------------------
void setup()
{
// Set sleep mode for main loop--interrupts will do all the work.
set_sleep_mode( SLEEP_MODE_IDLE );
sleep_enable();
// Setup outputs.
pinMode( OUTPUT_PIN, OUTPUT );
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT_PULLUP);
//---------------------------------
// Setup timer 1 for input capture.
//---------------------------------
// Disable timer for setup.
TCCR1B = 0x00;
// Reset timer count.
TCNT1 = 0x00;
// Clear interrupt flags.
TIFR1 = 0x00;
// Enable interrupts.
TIMSK1 =
( 1 << ICIE1 ) // Timer/Counter1, Input Capture Interrupt Enable.
| ( 1 << OCIE1A ); // Timer/Counter1, Output Compare A Match Interrupt Enable.
// Timer/Counter1 Control Register A to default normal operation.
// (There were changed by the Arduino startup code.)
TCCR1A = 0;
TCCR1B = 0;
// Setup Input Capture and clock divide rate.
TCCR1B =
( 1 << ICNC1 ) // Enable Input Capture Noise Canceler.
| ( 1 << ICES1 ) // Set Input Capture Edge Select to rising edge.
| ( 1 << CS11 ) | ( 1 << CS10 ); // Clock Select to clk/64.
}
//-------------------------------------------------------------------------------------------------
// USES:
// Main loop. Just sleeps and allows interrupts to do the work.
//-------------------------------------------------------------------------------------------------
void loop()
{ // read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// Schalter "ein" Signal x2:
int MULTIPLIER = 2;
// turn LED on:
digitalWrite(ledPin, HIGH);
} else {
// Schalter "aus" Signal geht durch:
int MULTIPLIER = 4;
// turn LED off:
//digitalWrite(ledPin, LOW);
}
{
// Put the device to sleep:
sleep_mode();
}
}
Ich habe probiert, im loop den Schalter auszulesen, das funktioniert ja, aber ich habe leider keine Idee, wie und wo im Programm man den Wert "MULTIPLIER" im Betrieb verändern kann.
Die Verwendung von "enum" ist ja für mich nicht zwingend erforderlich, aber wenn der Code schon wie gewünscht funktioniert, würde ich ihn gerne im wesentlichen belassen ...
Vielen Dank für eure Zeit und Hilfestellung
Peter