Skip to content

Commit

Permalink
Documentation and example updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ArminJo committed Aug 26, 2020
1 parent 5cf06ac commit 03bb7ea
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 20 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ Available as Arduino library "FrequencyDetector"
[![Commits since latest](https://img.shields.io/github/commits-since/ArminJo/Arduino-FrequencyDetector/latest)](https://github.com/ArminJo/Arduino-FrequencyDetector/commits/master)
[![Build Status](https://github.com/ArminJo/Arduino-FrequencyDetector/workflows/LibraryBuildWithAction/badge.svg)](https://github.com/ArminJo/Arduino-FrequencyDetector/actions)
[![Build Status](https://github.com/ArminJo/Arduino-FrequencyDetector/workflows/LibraryBuildWithScript/badge.svg)](https://github.com/ArminJo/Arduino-FrequencyDetector/actions)
[![Build Status](https://github.com/ArminJo/Arduino-FrequencyDetector/workflows/LibraryBuildWithSteps/badge.svg)](https://github.com/ArminJo/Arduino-FrequencyDetector/actions)
[![Hit Counter](https://hitcounter.pythonanywhere.com/count/tag.svg?url=https%3A%2F%2Fgit.luolix.top%2FArminJo%2FArduino-FrequencyDetector)](https://github.com/brentvollebregt/hit-counter)

Detects frequency **from 38 Hz to 9612 Hz** and works even on an ATTiny85 with 1 MHz up to 4806 Hz. The input signal can be plotted to the Arduino Serial Plotter resulting in a **simple Oscilloscope** to test the internal signal.
Expand Down
3 changes: 2 additions & 1 deletion examples/SimpleFrequencyDetector/SimpleFrequencyDetector.ino
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ void setup() {
pinMode(LED_NO_TRIGGER, OUTPUT);

/*
* initialize FrequencyDetector
* initialize default values for high and low frequency and dropout counts for frequency detector.
*/
setFrequencyDetectorControlDefaults();

/*
* Set channel, reference, sample rate and threshold for low signal detection.
* Set reference to 1.1Volt for AC coupled signal.
Expand Down
16 changes: 16 additions & 0 deletions examples/WhistleSwitch/ShowInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,22 @@ void printBODLevel() {
printBODLevel(tHighFuseBits);
}

void printMCUSR(uint8_t aMCUSRContent) {
if (aMCUSRContent & (1 << WDRF)) {
Serial.print(F(" Watchdog"));
}
if (aMCUSRContent & (1 << BORF)) {
Serial.print(F(" Brownout"));
}
if (aMCUSRContent & (1 << EXTRF)) {
Serial.print(F(" Reset"));
}
if (aMCUSRContent & (1 << PORF)) {
Serial.print(F(" PowerOn"));
}
Serial.println();
}

/*
* Output description for all fuses except "DebugWire enabled"
*/
Expand Down
1 change: 1 addition & 0 deletions examples/WhistleSwitch/ShowInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ void Information(void);
void printBODLevel(uint8_t aHighFuseBits);
void printBODLevel();
void printFuses(void);
void printMCUSR(uint8_t aMCUSRContent);
void printBODSFlagExistence();
#endif // defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny87__)

Expand Down
57 changes: 43 additions & 14 deletions examples/WhistleSwitch/WhistleSwitch.ino
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
* INFO
* After power up or reset, the feedback LED echoes the range number. Range number 10 indicates an individual range, programmed by advanced programming.
* The timeout state is signaled by short LED pulses after the range number feedback (no short pulse -> no timeout enabled).
* If the button is pressed during the info / startup, the ADC ((AverageLevel + 50) / 100) is signaled after the timeout signaling.
* Range is from 0 to 10. Values of 4 to 6 are optimal.
*
* TIMEOUT
* After a timeout of TIMEOUT_RELAY_ON_SIGNAL_MINUTES_(1 to 3) (2, 4 or 8 hours) the relay goes OFF for 1 second.
Expand Down Expand Up @@ -129,10 +131,8 @@
* If not defined, the 1x amplification is used with a more digispark compatible pin layout
*/
//#define USE_ATTINY85_20X_AMPLIFICATION

//#define PRINT_RESULTS_TO_SERIAL_PLOTTER
//#define MEASURE_TIMING // do not activate for ATTinies since there is no timing pin left

//#define TRACE
//#define DEBUG
#if ! defined (INFO)
Expand Down Expand Up @@ -409,6 +409,7 @@ EEMEM EepromParameterStruct sPersistentParametersEEPROM;
* States for main loop
*/
enum MainStateEnum {
IN_SETUP,
DETECT_FREQUENCY,
PROGRAM_SIMPLE,
PROGRAM_ADVANCED_FREQUENCY_RANGE,
Expand All @@ -426,6 +427,7 @@ struct WhistleSwitchControlStruct {

uint32_t MillisAtLastRelayChange;
//
bool sSignalAverageLevel; // Signal (Average level / 100) at startup
bool RelayJustToggled; // do only one toggle per consecutive matches
bool sMatchTooLongDetected;
//
Expand Down Expand Up @@ -601,6 +603,19 @@ void signalRangeIndexByLed() {
}
}

/*
* Range is from 0 to 10. Values of 4 to 6 are optimal.
*/
void signalAverageLevelByLed() {
// display AverageLevel / 100
for (uint8_t i = 0; i <= (FrequencyDetectorControl.AverageLevel + 50) / 100; ++i) {
digitalWriteFast(LED_FEEDBACK, HIGH);
delay(TIMING_FREQUENCY_LOWER_MILLIS * 4);
digitalWriteFast(LED_FEEDBACK, LOW);
delay(TIMING_FREQUENCY_LOWER_MILLIS * 4);
}
}

void signalTimeoutByLed() {
#ifdef INFO
Serial.print(F("RelayOnTimeoutIndex="));
Expand Down Expand Up @@ -833,7 +848,7 @@ void MyInit(void) {
*******************************************************************************************/
void setup() {
#ifdef INFO
uint8_t tMCUSRStored=0;
uint8_t tMCUSRStored = 0;
if (MCUSR != 0) {
tMCUSRStored = MCUSR; // content of MCUSR register at startup
MCUSR = 0; // to prepare for next boot.
Expand Down Expand Up @@ -873,6 +888,8 @@ void setup() {
pinModeFast(LED_FEEDBACK, OUTPUT);
pinModeFast(RELAY_OUT, OUTPUT);

WhistleSwitchControl.MainState = IN_SETUP;

#ifdef INFO
// Just to know which program is running on my Arduino
Serial.print(F("\r\nSTART WhistleSwitch.cpp\r\nVersion " VERSION_EXAMPLE " from " __DATE__"\r\nMCUSR=0x"));
Expand All @@ -882,11 +899,6 @@ void setup() {
# endif
#endif

// initial state of whistle switch
backToStateDetect();
ButtonAtPin3.ButtonStateHasJustChanged = false;
WhistleSwitchControl.TimeoutSignaledOnce = false;

/*
* Set channel, reference, sample rate and threshold for low signal detection.
*/
Expand Down Expand Up @@ -920,19 +932,30 @@ void setup() {
*/
signalTimeoutByLed();
delay(1000);
readSignal(); // initialize values

//initPinChangeInterrupt
#if defined(__AVR_ATtiny85__)
GIFR = _BV(PCIF); // Must clear interrupt flag in order to avoid to call this ISR, when enabling interrupts below.
GIMSK = _BV(PCIE); //INT0 disable, PCINT enable
PCMSK = _BV(BUTTON_PIN);
// GIFR = _BV(PCIF); // Must clear interrupt flag in order to avoid to call this ISR, when enabling interrupts below.
// GIMSK = _BV(PCIE); //INT0 disable, PCINT enable
// PCMSK = _BV(BUTTON_PIN);
#else
// PCICR = _BV(PCIE2); //PCINT2 enable
// PCMSK2 = digitalPinToBitMask(BUTTON_PIN); // 0x20 - Pin 5 enable
#endif
#if defined(PRINT_RESULTS_TO_SERIAL_PLOTTER)
printLegendForArduinoPlotter(&Serial);
#endif

// initial state of whistle switch
backToStateDetect();
// ButtonAtPin3.ButtonStateHasJustChanged = false;
// WhistleSwitchControl.TimeoutSignaledOnce = false;

if (WhistleSwitchControl.sSignalAverageLevel) {
readSignal();
signalAverageLevelByLed();
}
}

/************************************************************************
Expand Down Expand Up @@ -1101,7 +1124,9 @@ void detectFrequency() {
}

#if defined(INFO) && ! (defined(DEBUG) || defined(PRINT_INPUT_SIGNAL_TO_PLOTTER) || defined(PRINT_RESULTS_TO_SERIAL_PLOTTER))
if (abs((int16_t)FrequencyDetectorControl.AverageLevel - (int16_t)sLastAverageLevel) > AVERAGE_LEVEL_DELTA_REQUIRED_FOR_OUTPUT) {
if (abs(
(int16_t )FrequencyDetectorControl.AverageLevel
- (int16_t )sLastAverageLevel) > AVERAGE_LEVEL_DELTA_REQUIRED_FOR_OUTPUT) {
sLastAverageLevel = FrequencyDetectorControl.AverageLevel;
printSignalInfos();
}
Expand Down Expand Up @@ -1247,6 +1272,10 @@ void detectSimpleProgrammingStateTimeout() {
*/
void handleButtonPress(bool __attribute__((unused)) aButtonToggleState) {
switch (WhistleSwitchControl.MainState) {
case IN_SETUP:
WhistleSwitchControl.sSignalAverageLevel = true;
break;

case DETECT_FREQUENCY:
if (ButtonAtPin3.checkForDoublePress(RESET_WAIT_TIMEOUT_MILLIS)) {
doReset();
Expand Down Expand Up @@ -1385,8 +1414,8 @@ void doReset() {
Serial.flush();
# endif
// Jump to 0x0000
void (*ptrToReset)() = 0; // pointer to reset
(*ptrToReset)(); // reset!
void (*ptrToReset)() = 0;// pointer to reset
(*ptrToReset)();// reset!
#else // defined (__AVR_ATmega328P__) || defined (__AVR_ATmega328__)
// second push happened before timeout -> perform reset (this does not work with arduino bootloader)
wdt_enable(WDTO_500MS);
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version=2.0.0
author=Armin Joachimsmeyer
maintainer=Armin Joachimsmeyer <armin.joachimsmeyer@gmail.com>
sentence=Measure the main frequency of analog captured signal connected to an Arduino and check for noise and mute.<br/>
paragraph=Detects frequency from 38 Hz to 9612 Hz and works even on an ATTiny85 with 1 MHz up to 4806 Hz. Signal can be delivered e.g. by a microphone. Tested for UNO, Nano and ATtiny85.<br/>Examples includes a whistle switch (Pfeiffschalter) designed to react to human whistling.<br/>Like <a href="https://www.arduino.cc/en/Tutorial/SimpleAudioFrequencyMeter"> Arduino Simple Audio Frequency Meter</a><br/><br/><b>New:</b> Arduino Serial Plotter output of input signal, renamed doPlausi() to doEqualDistributionPlausi().<br/>
paragraph=Detects frequency from 38 Hz to 9612 Hz and works even on an ATTiny85 with 1 MHz up to 4806 Hz. Signal can be delivered e.g. by a microphone. Tested for UNO, Nano and ATtiny85.<br/>Examples includes a whistle switch (Pfeiffschalter) designed to react to human whistling.<br/>Like <a href="https://www.arduino.cc/en/Tutorial/SimpleAudioFrequencyMeter"> Arduino Simple Audio Frequency Meter</a><br/><br/><b>New: </b> Arduino Serial Plotter output of input signal, renamed doPlausi() to doEqualDistributionPlausi().<br/>
category=Signal Input/Output
url=https://github.com/ArminJo/Arduino-FrequencyDetector
depends=ATtinySerialOut
Expand Down
13 changes: 10 additions & 3 deletions src/FrequencyDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ union Myword {
* aADCReference can be DEFAULT (VCC) or INTERNAL (1.1 volt) !! use the definitions
* aADCPrescalerValue can be one of PRESCALE4, PRESCALE8, PRESCALE32, PRESCALE64 or PRESCALE128
* aFrequencyOfOneSampleTimes100 depends on value of aADCPrescalerValue
* Formula is
*/
void setFrequencyDetectorReadingValues(uint8_t aADCChannel, const uint8_t aADCReference, uint8_t aADCPrescalerValue,
uint16_t aRawVoltageMinDelta) {
Expand Down Expand Up @@ -174,17 +173,23 @@ bool setFrequencyDetectorDropoutTimes(uint16_t aMinMatchNODropoutMillis, uint16_
#endif
return tRetval;
}

/*
* Initialize default values for high and low frequency and dropout counts for frequency detector.
*/
void setFrequencyDetectorControlDefaults() {
setFrequencyDetectorMatchValues(FREQUENCY_MIN_DEFAULT, FREQUENCY_MAX_DEFAULT);
setFrequencyDetectorDropoutCounts(MIN_NO_DROPOUT_COUNT_BEFORE_ANY_MATCH_DEFAULT,
MAX_DROPOUT_COUNT_BEFORE_NO_FILTERED_MATCH_DEFAULT);
}

/*
* Set channel, reference, sample rate and threshold for low signal detection.
* Set reference to 5 volt for AC coupled signal.
*/
void setFrequencyDetectorReadingDefaults() {
// for DC coupled signal
setFrequencyDetectorReadingValues(ADC_CHANNEL_DEFAULT, DEFAULT, PRESCALE_VALUE_DEFAULT, RAW_VOLTAGE_MIN_DELTA_DEFAULT);
// set reference to 1.1 volt for AC coupled signal - is equivalent to an additional signal amplification of around 4
// If you set reference to 1.1 volt for AC coupled signal you have the equivalence to an additional signal amplification of around 4
//setFrequencyDetectorReadingValues(ADC_CHANNEL_DEFAULT, INTERNAL1V1, PRESCALE_VALUE_DEFAULT, RAW_VOLTAGE_MIN_DELTA_DEFAULT);
}

Expand Down Expand Up @@ -213,6 +218,8 @@ uint16_t sReadValueBuffer[SIGNAL_PLOTTER_BUFFER_SIZE];
* !!! Timer0 interrupt, which counts the milliseconds is disabled during reading and enabled afterwards!!!
* The alternative of using disable interrupt is getting wrong results!!!
* The value of millis() is adjusted manually after reading.
*
* @return the frequency as detected during the reading
*/
uint16_t readSignal() {
Myword tUValue;
Expand Down

0 comments on commit 03bb7ea

Please sign in to comment.