You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
5.6 KiB
C
206 lines
5.6 KiB
C
/*
|
|
* geigerzaehler.c
|
|
*
|
|
* Created : 28.02.2019 09:07:22
|
|
* Author : John Ditgens, Alexander Brandscheidt
|
|
* Git-Repository : https://gitea.Railduction.eu/JohnD/Geigerzaehler.git
|
|
*
|
|
* MController : AtMega328P
|
|
* Board : Arduino Nano
|
|
*/
|
|
#define F_CPU 16000000UL // Clock speed: 16 MHz - Speed from onboard oscillator
|
|
|
|
// Imports
|
|
#include <avr/io.h>
|
|
#include <avr/interrupt.h>
|
|
#include <stdint.h>
|
|
|
|
/*
|
|
* Global variable declaration
|
|
*/
|
|
// Set frequencys and general stuff
|
|
uint16_t boost_frequency = 10000; // 10kHz frequency
|
|
uint16_t signalOutput_piezo_time = 200; // 200ms
|
|
uint16_t signalOutput_led_time = 200; // 200ms
|
|
|
|
// Used for execution-timing (with timer) [0 = disabled, >0 = nextTimerTick] (1 is next avaible execution)
|
|
uint16_t boost_highVoltage_nextTick = 1; // Execute at start
|
|
uint16_t signalOutput_piezo_nextTick = 0;
|
|
uint16_t signalOutput_led_nextTick = 0;
|
|
|
|
// Prescaling of timer [timer-speed: cpu-clock / prescaler]
|
|
// Modes: [1, 8, 64, 256, 1024]
|
|
uint16_t timer1_prescaler = 256;
|
|
uint16_t timer1_overflow_value = 65535; // For calculations
|
|
|
|
int main()
|
|
{
|
|
/*
|
|
* Init
|
|
*/
|
|
// Inputs
|
|
DDRD &= (0 << PORTD2); // Activate input PD2
|
|
DDRD &= (0 << PORTD3); // Activate input PD3
|
|
|
|
// Outputs
|
|
DDRD |= (1 << PORTD4);
|
|
DDRD |= (1 << PORTD5);
|
|
DDRD |= (1 << PORTD6);
|
|
DDRB |= (1 << PORTB5); // Onboard-Led
|
|
|
|
// Interrupts
|
|
// for INT0 Pin-D2 High-voltage check
|
|
EICRA |= (0 << ISC01)|(1 << ISC00); // On at any edge [Code: 01]
|
|
EIMSK |= (1 << INT0); // Activate Interrupt INT0
|
|
// for INT1 Pin-D3 Counter-click
|
|
EICRA |= (1 << ISC11)|(1 << ISC10); // On rising edge [Code: 11]
|
|
EIMSK |= (1 <<INT1); // Activate Interrupt INT1
|
|
|
|
// Init timer1
|
|
timer1_init();
|
|
|
|
PORTB |= (boost_highVoltage_nextTick << PORTB5); // Onboard-Led
|
|
|
|
// Endless loop
|
|
while (1)
|
|
{
|
|
cli(); // Deactivate global interrupts (before checks)
|
|
|
|
/*
|
|
* HighVoltage boosting
|
|
*/
|
|
if(boost_highVoltage_nextTick > 0) // If there is a nextTick
|
|
{
|
|
if((uint16_t)TCNT1 >= boost_highVoltage_nextTick && ((uint16_t)TCNT1-boost_highVoltage_nextTick) < (timer1_overflow_value/2)) // If we are on or after the tick it should be executed
|
|
{
|
|
// Flip pin state
|
|
PORTD ^= (1 << PORTD4);
|
|
|
|
// Calculate when next high/low should be set
|
|
boost_highVoltage_nextTick = (uint16_t)TCNT1 + F_CPU/timer1_prescaler * 1/boost_frequency/2; // Half of time it should be high/low
|
|
if(boost_highVoltage_nextTick == 0) boost_highVoltage_nextTick++; // If its 0, it stops, we dont want that
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Signal output
|
|
*/
|
|
// Piezo
|
|
if(signalOutput_piezo_nextTick > 0) // If there is a nextTick
|
|
{
|
|
if((uint16_t)TCNT1 >= signalOutput_piezo_nextTick && ((uint16_t)TCNT1-signalOutput_piezo_nextTick) < (timer1_overflow_value/2)) // If we are on or after the tick it should be executed
|
|
{
|
|
// Flip pin state
|
|
PORTD ^= (1 << PORTD5);
|
|
|
|
if(!(PIND & (1 << PORTD5)))
|
|
{
|
|
// We are on low (again), disable further execution
|
|
signalOutput_piezo_nextTick = 0;
|
|
}
|
|
|
|
// When the signal should next flip
|
|
signalOutput_piezo_nextTick = (uint16_t)TCNT1 + F_CPU/timer1_prescaler * signalOutput_piezo_time/1000; // Calculate nextTick based on time in ms
|
|
if(signalOutput_piezo_nextTick == 0) signalOutput_piezo_nextTick++; // If its 0, it stops, we dont want that
|
|
}
|
|
}
|
|
// LED
|
|
if(signalOutput_led_nextTick > 0) // If there is a nextTick
|
|
{
|
|
if((uint16_t)TCNT1 >= signalOutput_led_nextTick && ((uint16_t)TCNT1-signalOutput_led_nextTick) < (timer1_overflow_value/2)) // If we are on or after the tick it should be executed
|
|
{
|
|
// Flip pin state
|
|
PORTD ^= (1 << PORTD6);
|
|
|
|
if(!(PIND & (1 << PORTD6)))
|
|
{
|
|
// We are on low (again), disable further execution
|
|
signalOutput_led_nextTick = 0;
|
|
}
|
|
|
|
// When the signal should next flip
|
|
signalOutput_led_nextTick = (uint16_t)TCNT1 + F_CPU/timer1_prescaler * signalOutput_led_time/1000; // Calculate nextTick based on time in ms
|
|
if(signalOutput_led_nextTick == 0) signalOutput_led_nextTick++; // If its 0, it stops, we dont want that
|
|
}
|
|
}
|
|
}
|
|
|
|
sei(); // Activate global interrupts (after checks) [when an interrupt was fired, it will now be executed]
|
|
}
|
|
|
|
/*
|
|
* Init timer1 (16-bit) in "normal mode"
|
|
*/
|
|
void timer1_init()
|
|
{
|
|
// set up timer with speed: cpu-clock / prescaler
|
|
switch(timer1_prescaler){ // [CS12 CS11 CS10]
|
|
default:
|
|
case 1:
|
|
TCCR1B |= (1 << CS10); // [0 0 1 ]
|
|
break;
|
|
|
|
case 8:
|
|
TCCR1B |= (1 << CS11); // [0 1 0 ]
|
|
break;
|
|
|
|
case 64:
|
|
TCCR1B |= (1 << CS10); // [0 1 1 ]
|
|
TCCR1B |= (1 << CS11);
|
|
break;
|
|
|
|
case 256:
|
|
TCCR1B |= (1 << CS12); // [1 0 0 ]
|
|
break;
|
|
|
|
case 1024:
|
|
TCCR1B |= (1 << CS10); // [1 0 1 ]
|
|
TCCR1B |= (1 << CS12);
|
|
break;
|
|
}
|
|
|
|
// initialize counter
|
|
TCNT1 = (uint16_t)0;
|
|
}
|
|
|
|
|
|
/*
|
|
* ISR - Interrupt service routine
|
|
*/
|
|
// Address: 0x001 INT0 - On any edge [Code: 01]
|
|
// Handles: Over/Below working voltage
|
|
ISR(INT0_vect)
|
|
{
|
|
if(!(PIND & (1 << PORTD2))) // Falling edge
|
|
{
|
|
// Below ~400V, activate booster
|
|
boost_highVoltage_nextTick = TCNT1; // Run as soon as possible
|
|
PORTB |= (1 << PORTB5); // Onboard-Led
|
|
|
|
PORTB |= (1 << PORTB5); // Onboard-Led
|
|
}
|
|
else // Rising edge
|
|
{
|
|
// Reached ~400V, deactivate booster
|
|
boost_highVoltage_nextTick = 0;
|
|
|
|
PORTB |= (0 << PORTB5); // Onboard-Led
|
|
|
|
// reset state
|
|
PORTD |= (0 << PORTD4); // pin on low
|
|
}
|
|
|
|
reti(); // Exit interrupt-handler
|
|
}
|
|
|
|
// Address: 0x002 INT1 - On rising edge [Code: 11]
|
|
// Handles: Counter tube "tick"
|
|
ISR(INT1_vect)
|
|
{
|
|
// Tick detected, signalOutput
|
|
signalOutput_piezo_nextTick = TCNT1; // Run as soon as possible
|
|
signalOutput_led_nextTick = TCNT1;
|
|
|
|
reti(); // Exit interrupt-handler
|
|
}
|