User Tools

Site Tools


projects:arduino_with_dragon_attiny13

Differences

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

Link to this comparison view

Next revision
Previous revision
projects:arduino_with_dragon_attiny13 [2020/07/26 19:18] – created adminprojects:arduino_with_dragon_attiny13 [2020/10/11 19:20] (current) admin
Line 1: Line 1:
-====== Arduino IDE with AVR Dragon and ATTINY13 ======+====== Arduino IDE with AVR Dragon and ATtiny13 ======
  
-This page describes how to add the AVR Dragon as programmer to the Arduino IDE, compile for ATTINY13 and program as such the ATTINY13 directly from within the Arduino IDE.+This page describes how to add the AVR Dragon as programmer to the Arduino IDE, compile for ATtiny13 and program as such the ATtiny13 directly from within the Arduino IDE.
  
 ==== Add ATTINY13 hardware package ==== ==== Add ATTINY13 hardware package ====
Line 40: Line 40:
 ==== Getting started ==== ==== Getting started ====
 Follow the link to the connection diagram at the official github page [[https://github.com/MCUdude/MicroCore#getting-started-with-microcore|getting-started-with-microcore]] will show how to connect the ATtiny13 to the AVR Dragon. Follow the link to the connection diagram at the official github page [[https://github.com/MCUdude/MicroCore#getting-started-with-microcore|getting-started-with-microcore]] will show how to connect the ATtiny13 to the AVR Dragon.
 +
 +Start with burning the bootloader from within arduino. (Tools -> Burn Bootloader)
  
 Then add following blink code: Then add following blink code:
Line 57: Line 59:
  
 And compile, program and observe that pin 3 alternates between 0v and 5v in a 1s interval And compile, program and observe that pin 3 alternates between 0v and 5v in a 1s interval
 +
 +<code c>
 +/*
 + * Output test
 + */
 +
 +/*
 + * pinout:
 + * https://camo.githubusercontent.com/b621cdf0625c6a9e961bb3ac5c94c46198f7585d/687474703a2f2f692e696d6775722e636f6d2f4a7362677550562e6a7067
 + */
 +
 +#define P1_PB5 5
 +#define P2_PB3 3
 +#define P3_PB4 4
 +#define P5_PB0 0
 +#define P6_PB1 1
 +#define P7_PB2 2
 +
 +// the setup function runs once when you press reset or power the board
 +void setup() {
 +  pinMode(P2_PB3, OUTPUT);
 +  pinMode(P5_PB0, OUTPUT);
 +  pinMode(P6_PB1, OUTPUT);
 +  pinMode(P7_PB2, OUTPUT);
 +}
 +
 +// the loop function runs over and over again forever
 +void loop() {
 +  for (int i=0; i <= 255; i++) {
 +    digitalWrite(P2_PB3, (i & 1) ? HIGH : LOW);
 +    digitalWrite(P5_PB0, (i & 2) ? HIGH : LOW);
 +    digitalWrite(P6_PB1, (i & 4) ? HIGH : LOW);
 +    digitalWrite(P7_PB2, (i & 8) ? HIGH : LOW);
 +    delay(500);
 +  }
 +}
 +</code>
 +
 +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.1595783895.txt.gz · Last modified: 2020/07/26 19:18 by admin