0

Friend asked me to find problem with compilation for his DigiSpark AT Tiny85 board. We are trying to compile sketch from here: https://forum.arduino.cc/index.php?topic=314773.0

But with no luck - there is something mixed in headers or configuration and I do not know what exactly.

This ISR does not compile:

ISR(TIMER1_OVF_vect) { //timer1 overflow

First there were some errors like TCCR1 = 0; not defined in this sketch, then after playing with #define __ AVR_ATtiny85__, #undef _AVR_IOXXX_H_ and replacing avr/io.h with iotn85.h errors like multiple definition of __vector_x(?) came. Commenting out this line:
//attachInterrupt(0,zeroCrossingInterrupt, FALLING)
helped, but now even this one works, but ISR not.

I know there is a lot of caches and you do not see what is going on behind curtains, but I am quite lost yet...

Maybe there is also problem I have multiple installs in different dirs, but do not know how to clean old ones (1.6.5-r2) and at the end both work same way now, my latest fresh installed is 1.8.9.

Does anyone have any experiences with or some working demo sketch using both compare match and overflow ISRs ?

Edit
Setup info
This board selected (...\AppData\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.7\boards.txt):

digispark-tiny.name=Digispark (Default - 16.5mhz)
digispark-tiny.upload.using=micronucleusprog
digispark-tiny.upload.protocol=usb
digispark-tiny.upload.tool=micronucleus
digispark-tiny.upload.maximum_size=6012
digispark-tiny.build.mcu=attiny85
digispark-tiny.build.f_cpu=16500000L
digispark-tiny.build.board=AVR_DIGISPARK
digispark-tiny.build.core=tiny
digispark-tiny.build.variant=digispark
digispark-tiny.upload.wait_for_upload_port = false
digispark-tiny.upload.use_1200bps_touch = false
digispark-tiny.upload.disable_flushing = false

And these are available:

(...\AppData\Roaming\Arduino15\package_digistump_index.json)
...
"boards": [
  {
    "name": "Digispark (Default - 16.5mhz)"
  },
  {
    "name": "Digispark Pro (Default 16 Mhz)"
  },
  {
    "name": "Digispark Pro (16 Mhz) (32 byte buffer)"
  },
  {
    "name": "Digispark Pro (16 Mhz) (64 byte buffer)"
  },
  {
    "name": "Digispark (16mhz - No USB)"
  },
  {
    "name": "Digispark (8mhz - No USB)"
  },
  {
    "name": "Digispark (1mhz - No USB)"
  }
],
...

Edit 2
Fresh install attempt on W10
Few more links - 2nd manual here:
https://www.electronicshub.org/getting-started-with-attiny85/

http://digistump.com/package_digistump_index.json
have to be translated to
https://raw.githubusercontent.com/digistump/arduino-boards-index/master/package_digistump_index.json

https://downloads.arduino.cc/arduino-1.8.9-windows.zip
W10
When installing shows error downloading (timeout?):
http://downloads.arduino.cc/tools/avr-gcc-4.8.1-arduino5-i686-mingw32.zip

Downloaded by hand to (there was empty file of this name):
...\AppData\Local\Arduino15\staging\packages\
avr-gcc-4.8.1-arduino5-i686-mingw32.zip

...\AppData\Local\Temp\arduino_build_139604\core\core.a(wiring.c.o): In function `__vector_4':

...\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny/wiring.c:93: multiple definition of `__vector_4'

...\AppData\Local\Temp\arduino_build_139604\sketch\sketch_jun28a.ino.cpp.o:...\arduino-1.8.9\SketchBook\sketch_jun28a/sketch_jun28a.ino:60: first defined here

collect2.exe: error: ld returned 1 exit status

exit status 1 Error compiling for board Digispark (Default - 16.5mhz).

...\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny\core_build_options.h (not found that file in arduino dir):

/*=============================================================================
  Build options for the ATtiny85 processor
=============================================================================*/

#if defined( __AVR_ATtiny25__ ) || defined( __AVR_ATtiny45__ ) || defined( __AVR_ATtiny85__ )
#define __AVR_ATtinyX5__
#endif

#if defined( __AVR_ATtinyX5__ )

/*
  For various reasons, Timer 1 is a better choice for the millis timer on the
  '85 processor.
*/
#define TIMER_TO_USE_FOR_MILLIS                   1
6
  • Btw made best compression and speed-up of Adafruit fonts (to aprox. 1/2 better than LZW) and C++ .Net simulator for old AT Mega project setup if someone interested (it compiles Arduino code directly, but few files mocked and does not work in all versions - engine "black magic" changes often.
    – Jan
    Jun 27, 2019 at 21:13
  • The code from the site seems ok. From the error message it seems, as if you are not choosing the correct board type in the Arduino IDE. Since the ATTiny85 is not in the standard core library: What core for ATTiny do you have installed?
    – chrisl
    Jun 27, 2019 at 22:00
  • He sent me a link instructables.com/id/Digispark-DIY-The-smallest-USB-Arduino/… how to setup, thought I used the same, but remember I selected Default 16.5MHz - maybe from manual from a different page and now I see there is mentioned Tiny core ?? Will check that later too - not sure if there was this option. Did not installed drivers as I do not have the module and there was nothing related in that zip.
    – Jan
    Jun 28, 2019 at 3:26
  • More info added to question, checked all boards, Tiny85 mentioned also @all 3 non-pro versions.
    – Jan
    Jun 28, 2019 at 3:50
  • Please look into the file "arduino folder/packages/digistump/hardware/avr/1.6.7/cores/tiny/core_build_options.h". What number is used for the #define TIMER_TO_USE_FOR_MILLIS?
    – chrisl
    Jun 28, 2019 at 8:01

3 Answers 3

1

The problem is the following:

The digispark core already implements the TIMER1_OVF_vect ISR (Timer1 Overflow Interrupt). Since you have a 1 for the #define TIMER_TO_USE_FOR_MILLIS, Timer1 will be used for counting the millis() value in the background. For this the Timer 1 Overflow interrupt is needed.

The code, that you copied from that site, does not anticipate, that you might use a core, that already implements the interrupts. It is written for a generic ATtiny85, not specifically for the Digispark version.

What you can do to solve the problem:

  • You can use Timer0 for your code, keeping the Digispark core untouched. You can change all registers from Timer1 to Timer0 (by replacing the 1 with a 0). Additionally you need to replace TCCR1 with TCCR0B, because for Timer0 that's the register, that set's the prescaler (and turns the timer off if zero is written to it). Also you need to consider, that Timer0 has other prescaler settings. So the line TCCR1 = B00001011; in zeroCrossingInterrupt() must be changed to TCCR0B = B00000101;. That will set the prescaler to 1024 as mentioned in the comment. The resulting code compiles fine for me with the digispark core (though I have not tested it's functionality).

  • You can set the Digispark core to use Timer0 for millis(), by changing the definition of TIMER_TO_USE_FOR_MILLIS in the Attiny85 section of the file arduino_folder/packages/digistump/hardware/avr/1.6.7/cores/tiny/core_build_options.h to the value 0 instead of 1. If you do this, the original sketch compiles fine. Though the comment before that build options states, that Timer1 is better for millis() "for various reasons", which is not very specific. You can try, if it works good for you.

  • You can use another Attiny core. Though you might have to change it too, to accomodate for the unusual clock frequency fo 16.5MHz (most cores I have seen have 16, 8 and 1MHz). That might be as easy as changing the value of the defined clock speed in the cores files, but I'm not sure about that.

4
  • Excellent ! Will try it, hope also he will understand it as non-professional programmer and accept your answer. You can teach how to fight with this insane system 4 dummies ;-) You know making things simple often make them tangled...
    – Jan
    Jun 29, 2019 at 4:49
  • Btw in case you will need to reduce GFX fonts size twice and speed up printing or compile and run Arduino + LCD code on PC, check my Github - lib maintainers defend against improvements.
    – Jan
    Jun 29, 2019 at 6:42
  • When I changed the millis value for 1 to 0, the compile error disappeared but the program did not load properly. I tried to load a simple blink blink sketch, it can not load any more. It doesn't seem to communicate anymore ! Anyway this is probably a "feature" not a bug - bad architecture concept...
    – Jan
    Jul 2, 2019 at 5:14
  • The upload has nothing to do with the compilation. You just are seeing another problem. I guess you are seeing some "programmer is not responding" error. Try google it, because this common error was answered several times on this site
    – chrisl
    Jul 2, 2019 at 6:27
1

Another simple option - rewrite or remove the ISR in wiring.c: ...\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny\wiring.c

For example after changing like this was able to compile without problems.

Simplest solution would be to put that code to my ISR too or call one from another.

#ifdef nothing
// bluebie changed isr to noblock so it wouldn't mess up USB libraries
ISR(MILLISTIMER_OVF_vect, ISR_NOBLOCK)
{
  // copy these to local variables so they can be stored in registers
  // (volatile variables must be read from memory on every access)
  unsigned long m = millis_timer_millis;
  unsigned char f = millis_timer_fract;

/* rmv: The code below generates considerably less code (emtpy Sketch is 326 versus 304)...

  m += MILLIS_INC;
  f += FRACT_INC;
  if (f >= FRACT_MAX) {
    f -= FRACT_MAX;
    m += 1;
  }
...rmv */

  f += FRACT_INC;

  if (f >= FRACT_MAX) 
  {
    f -= FRACT_MAX;
    m = m + MILLIS_INC + 1;
  }
  else
  {
    m += MILLIS_INC;
  }

  millis_timer_fract = f;
  millis_timer_millis = m;
  millis_timer_overflow_count++;
}
#endif

If you rename wiring.c and restart editor, you get main.cpp:5: undefined reference to `init' error, there is that "crappy" heart of arduino:

#include <WProgram.h>

int main(void)
{
    init();

    setup();

    for (;;)
        loop();

    return 0;
}

WProgram.h starts with:

#ifndef WProgram_h
#define WProgram_h

#include <stdlib.h>
#include <string.h>
#include <math.h>

#include <avr/interrupt.h>

#include "core_build_options.h"
#include "core_pins.h"
#include "wiring.h"
...

And init of that ATtiny85 (inside wiring.c) evn looks like this:

void init(void)
{
  // clock calibration stuff
  // recalibrate clock if it was calibrated by bootloader (like micronucleus)
  #if F_CPU != 16500000L
    if (OSCCAL != read_factory_calibration()) {
      // adjust the calibration down from 16.5mhz to 16.0mhz
      if (OSCCAL >= 128) {
        // maybe 8 is better? oh well - only about 0.3% out anyway
        OSCCAL -= 7;
      } else {
        OSCCAL -= 5;
      }
    }
  #endif

  // TODO: detect if fuses set to PLL, regular internal oscillator or external and change behaviour in this next section...
  #if F_CPU < 16000000L
    cli();
    CLKPR = 0b10000000;
    #if F_CPU == 8000000L
      CLKPR = 1; // div 2
    #elif F_CPU == 4000000L
      CLKPR = 2 // div 4
    #elif F_CPU == 2000000L
      CLKPR = 3; // div 8
    #elif F_CPU == 1000000L
      CLKPR = 4; // div 16
    #elif F_CPU == 500000L
      CLKPR = 5; // div 32 = 500khz
    #elif F_CPU == 250000L
      CLKPR = 6; // div 64 = 250khz
    #elif F_CPU == 125000L
      CLKPR = 7; // div 128 = 125khz cpu clock
    #else
      #warning "Cannot prescale chip to specified F_CPU speed"
    #endif
  #endif

  // this needs to be called before setup() or some functions won't work there
  sei();

  // In case the bootloader left our millis timer in a bad way
  #if defined( HAVE_BOOTLOADER ) && HAVE_BOOTLOADER
    MillisTimer_SetToPowerup();
  #endif

  // Use the Millis Timer for fast PWM
  MillisTimer_SetWaveformGenerationMode( MillisTimer_(Fast_PWM_FF) );

  // Millis timer is always processor clock divided by MillisTimer_Prescale_Value (64)
  MillisTimer_ClockSelect( MillisTimer_Prescale_Index );

  // Enable the overlow interrupt (this is the basic system tic-toc for millis)
  MillisTimer_EnableOverflowInterrupt();

  // Initialize the timer used for Tone
  #if defined( INITIALIZE_SECONDARY_TIMERS ) && INITIALIZE_SECONDARY_TIMERS
    initToneTimerInternal();
  #endif

  // Initialize the ADC
  #if defined( INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER ) && INITIALIZE_ANALOG_TO_DIGITAL_CONVERTER
    ADC_PrescalerSelect( ADC_ARDUINO_PRESCALER );
    ADC_Enable();
  #endif
}
1

I had similar problem. I removed functions loop() and setup() and I used classic C construction with main() function and it started to work. (I think loop() and setup() enables using of other functions like delay() - and it uses timer - only my hypothesis).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.