Site Tools


projects:arduino_with_dragon_attiny13

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
projects:arduino_with_dragon_attiny13 [2020/10/11 19:16] adminprojects:arduino_with_dragon_attiny13 [2020/10/11 19:20] (current) admin
Line 98: Line 98:
  
 Now you can easy verify if all pins are correctly controlled: Pin 2 should show every 0.5 second a change, Pin 5 should show every second, pin 6 every 2 seconds and pin 7 every 4 seconds. Now you can easy verify if all pins are correctly controlled: Pin 2 should show every 0.5 second a change, Pin 5 should show every second, pin 6 every 2 seconds and pin 7 every 4 seconds.
 +
 +===== Burst Controller =====
 +<code c>
 +/**
 + * ESD burst control
 + * Controllersoftware for switching output pins in a sequence
 + * based on a trigger from one input pin.
 + 
 + * The output pins control 3 high voltage relays and one
 + * trigger output for measurement purposes.
 + 
 + * Input pin uses gpio and timer based interrupt to handle 
 + * debouncing and signal edge processing. This simplifies
 + * processing a great deal.
 + 
 + * Hardware is based on the ATTINY13 8-bit microcontroller.
 + * Development was done with Arduino IDE, extended with the
 + * MicroCore, installed via: 
 + * Arduino Preferences -> Additional Boards Manager URLs
 +   https://mcudude.github.io/MicroCore/package_MCUdude_MicroCore_index.json
 + * And then selected via Tools -> Board -> MicroCore -> ATtiny13
 + * The device is programmed using ISP programming with the AVR Dragon.
 + * From within Arduino the ATtiny13 can then be programmed with the Upload
 + * button. The selected programmer is the DragonISP.
 + 
 + * You need to edit the programmers.txt file in Arduino:
 +   $HOME/.arduino15/packages/MicroCore/hardware/avr/1.0.6/programmers.txt
 + 
 + * See here for details:
 +   https://www.auditeon.com/projects:arduino_with_dragon_attiny13
 + 
 + * For pinout, see following page:
 + * https://github.com/MCUdude/MicroCore
 + *
 + * License: MIT
 + * Author: Marc Nijdam 10-10-2020
 + */
 +
 +
 +#define ARRAY_SIZE(x)  (sizeof(x) / sizeof(x[0]))
 +
 +#define P1_PB5_NC 5
 +#define P2_PB3_TRIGOUT 3
 +#define P3_PB4_TOGGLESW 4
 +#define P5_PB0_CHARGE 0
 +#define P6_PB1_DSCHRG 1
 +#define P7_PB2_ALLOFF 2
 +
 +#define STOP 255
 +
 +/**
 + * pin name and active state
 + */
 +const struct {
 +  const uint8_t pin; // pin name
 +  const uint8_t das; // default active state
 +} io[] = {
 +  [0] = {P7_PB2_ALLOFF ,1}, // bit 0, active high
 +  [1] = {P2_PB3_TRIGOUT,1}, // bit 1, active high
 +  [2] = {P6_PB1_DSCHRG ,0}, // bit 2, active low
 +  [3] = {P5_PB0_CHARGE ,0}, // bit 3, active low
 +  [4] = {P1_PB5_NC ,1}      // reset pin
 +  
 +};
 +
 +/**
 +  ____> charge -------------> (i.e. on high, switch closes)
 + * | ___> discharge ----------> (i.e. on high, switch closes)
 + * || __> trigout + pulldown -> (i.e. on high, trigger goes up.)
 + * ||| _> all off ------------> (i.e. on high, it connects output to gnd)
 + * ||||
 + * 0000
 + *
 + * 0: not active 
 + * 1: active
 + */
 +const struct {
 +  const uint8_t bits; // bitpattern for gpio output pins
 +  const uint16_t dur; // duration in ms
 +} patterns[] = {
 +  {0b0000,  100}, /*  charge   */
 +  {0b0000,  100}, /*         */
 +  {0b1000,    0}, /*    \ /    */
 +  {STOP, 0},      /*   _____   */
 +  {0b0101,    0}, /*           */
 +  {0b0110, 5000}, /*    / \    */
 +  {0b0010,    0}, /*         */
 +  {0b0000,  500}, /*         */
 +  {0b0000,  100}, /* discharge */
 +};
 +
 +/* counter which points to index of array */
 +volatile uint8_t processing;
 +volatile uint8_t pat_idx;
 +volatile uint8_t mode; // 0: charge, 1: discharge
 +
 +void setup() {
 +  /* initialize digital in- and output pins */
 +  pinMode(P3_PB4_TOGGLESW, INPUT_PULLUP);
 +  for (uint8_t i=0; i < ARRAY_SIZE(io); i++) {
 +    pinMode(io[i].pin, OUTPUT);
 +  }
 +
 +  mode = digitalRead(P3_PB4_TOGGLESW); // switch: 0=charging, 1=discharging
 +
 +  /* initialize flag, 0: processing not initiated, 1: processing */
 +  processing = 0;
 +
 +  /* enable interrupt from PB4 */
 +  setup_gpio_interrupt(P3_PB4_TOGGLESW);
 +  enable_pcint_interrupt();
 +
 +  /* enable interrupt from timer for semi-automatic with 1x 0.12ms debounce */
 +  setup_timer_interrupt(1);
 +
 +  /* enable all interrupts */
 +  sei();
 +}
 +
 +// the loop function runs over and over again forever
 +void loop() {
 +  if (!processing) {
 +    processing = 1;
 +    process_sequence(mode);
 +  }
 +}
 +
 +void process_sequence(uint8_t md) {
 +  pat_idx = md ? ARRAY_SIZE(patterns) - 1 : 0;
 +  for (;;) {
 +    set_bits(patterns[pat_idx].bits);
 +    /* wait ms duration, unless interrupted by switch */
 +    if (wait_ms(patterns[pat_idx].dur)) return;
 +    pat_idx += 1 - 2*md;
 +    if (patterns[pat_idx].bits == STOP) return;
 +  }
 +}
 +
 +/**
 + * Set bit pattern onto gpio output
 + * take into account active state
 + */
 +void set_bits(uint8_t bits) {
 +  for (uint8_t i=0; i < ARRAY_SIZE(io); i++) {
 +    digitalWrite(io[i].pin, !io[i].das ^ (( (1 << i) & bits) ? HIGH : LOW));
 +  }
 +}
 +
 +uint8_t wait_ms(uint16_t d) {
 +  unsigned long ts = millis() + d;
 +  for (;;) {
 +    if (millis() >= ts) return 0;
 +    if (!processing) return 1;
 +    delay(1);
 +  }
 +}
 +
 +void setup_gpio_interrupt(uint8_t port) {
 +  pinMode(port, INPUT_PULLUP);
 +  MCUCR |=  (1<<ISC00); // Trigger INT0 on rising edge
 +  MCUCR &= ~(1<<ISC01); // Trigger INT1 on rising edge
 +  PCMSK |= (1<<PCINT4); // pin change mask: listen to portb, pin PB4
 +}
 +
 +/**
 + * enable PCINT interrupt
 + */
 +void enable_pcint_interrupt(void) {
 +  GIMSK |= (1<<PCIE);
 +}
 +
 +/**
 + * disable PCINT interrupt
 + */
 +void disable_pcint_interrupt(void) {
 +  GIMSK &= ~(1<<PCIE);
 +}
 +
 +/**
 + * @brief setup timer interrupt
 + * @param duration in unit of +/- 0.125ms
 + */
 +void setup_timer_interrupt(uint8_t d) {
 +  TCCR0A |= _BV(WGM01); // set timer counter mode to CTC
 +  TCCR0B |= _BV(CS02)|_BV(CS00); // set prescaler to 1024 (CLK=1200000Hz/1024/256=4.57Hz, 0.22s)
 +  OCR0A = d; // set Timer's counter max value
 +}
 +
 +void enable_timer_interrupt(void) {
 +  TIMSK0 |= _BV(OCIE0A); // enable Timer CTC interrupt
 +}
 +
 +void disable_timer_interrupt(void) {
 +  TIMSK0 &= ~_BV(OCIE0A); // disable Timer CTC interrupt
 +}
 +
 +ISR(PCINT0_vect) // Interrupt on Int0 vector
 +{
 +  disable_pcint_interrupt();
 +  /* prevent false interrupt from switch, only allow toggle */
 +  if (mode != digitalRead(P3_PB4_TOGGLESW)) {
 +    mode = digitalRead(P3_PB4_TOGGLESW);
 +    processing = 0;
 +  }
 +  /* use timer interrupt for debouncing */
 +  enable_timer_interrupt();  
 +}
 +
 +ISR(TIM0_COMPA_vect) // Interrupt on Timer0 vector
 +{
 +  disable_timer_interrupt();
 +  enable_pcint_interrupt();
 +}
 +</code>
projects/arduino_with_dragon_attiny13.1602436605.txt.gz · Last modified: 2020/10/11 19:16 by admin