Help with attiny4 coding - Page 1
Forum section: electronics / beginners

author: minipower
author_rank: Contributor
timestamp: November 14, 2020, 01:14:29 am
content: I have no idea what I'm doing. But reading and cramming the info, this what I have come up with.Getting your feedback and recommendations would help me a lot.I'm trying to blink 2 led's in sequence over and over.To save as much 3v coin cell power. I am trying to put the attiny4 into the slowest CPU clock, since I'm only blinking led's - turn everything off except the internal low-power 128khz clock.Set pins 1(PB0) and 3(PB1) to outputs.To help save power. Set pins 4(PB2) and 6(PB3) to inputs with pull-up resistors.blink Red led 4 times then short pause. Then Green led 5 times then long pauseStart the blinking loop over and over.I have been studying these webpages.https://arduinoelectronics.wordpress.com/2014/01/06/ultra-low-power-led-flasher-with-attiny/https://sites.google.com/site/dannychouinard/Home/atmel-avr-stuff/low-powerhttps://www.garlicsoftware.com/articles/files/0662584a661f5b1cdb84dc2c17935537-1.phpI have attached a block diagram of what I'm trying to accomplish.This is the code I have so far. As you can see. I'm not sure if I have correctly put the cpu in slowest mode and turned on the internal low-power 128khz clock.Code:/** 2 leds.c** Created: 11/10/2020 11:27:18 AM* Author : rascal*/#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>#include <avr/wdt.h>#include <avr/delay.h>#define RED PB0#define GREEN PB1int main(void){cli(); // Disable global interrupts before initializationCCP-0xD8; // Unlock protected registerCLKPSR=256; // Clock division factor 256 (1000)CKSEL=11CLKPR=(1<<CLKPCE); CLKPR=256; // Low-power 128Khz clock / 256 = ?Khz/*or?CLKPR=(1<<CLKPCE); CLKPR=4; // 128Khz / 16 = 8Khzor?CLKPR=(1<<CLKPCE); CLKPR=8; // Clock/256CLKPS=(1<<4); // Clock division factor 256 (1000)*/PRR|=(1<<PRTIM0); // Turn timer0 offPRR|=(1<<PRTIM1); // Turn timer1 offDDRB=b0011; // Pins 4 & 6 inputs - Pins 1 & 3 outputsPUEB=|=(1<<PB2)|(1<<PB3) // Enable Pullup Resistor Pins 4 & 6ACSR|=(1<<ACD); // Turn off Analog comparator//DDRB|=(1<<RED)|(1<<GREEN); // Set pins 1 & 3 output/* or ?DDRB|= (1 << RED); // Set pin 1 outputDDRB|= (1 << GREEN); // Set pin 3 output*/setup_watchdog(9); // WDT prescale select 0-9// 0=16ms, 1=32ms, 2=64ms, 3=125ms, 4=250ms, 5=500ms// 6=1 sec, 7=2 sec, 8=4 sec, 9=8secsei(); //initialize global interrupts before beginning loop/* Replace with your application code */while (1){// Blink PB0 (RED led) 4 times then sleepPORTB |=(1<<RED); // 1 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msPORTB &=~(1<<RED); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msPORTB |=(1<<RED); // 1 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msPORTB &=~(1<<RED); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msPORTB |=(1<<RED); // 1 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msPORTB &=~(1<<RED); // turn the LED off by making the voltage LOWsleep_enable();sleep_cpu(); //sleep// Blink PB0 (GREEN led) 5 times then sleepPORTB |=(1<<GREEN); // 1 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msPORTB |=(1<<GREEN); // 2 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msPORTB |=(1<<GREEN); // 3 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msPORTB |=(1<<GREEN); // 4 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msPORTB |=(1<<GREEN); // 5 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOWsleep_enable(); // 2 sleep modes to extend the (pause) not blinking timesleep_cpu();sleep_enable(); // 2 sleep modes to extend the (pause) not blinking timesleep_cpu();}ISR (WDT_vect) {WDTCR |= _BV(WDIE);}

author: rstofer
author_rank: Super Contributor
timestamp: November 14, 2020, 01:53:33 am
content: I don't think this will compile:CCP-0xD8; // Unlock protected register

author: minipower
author_rank: Contributor
timestamp: November 14, 2020, 02:12:38 am
content: I think I see what your talking aboot.WrongCCP-0xD8; // Unlock protected registerCorrectCCP=0xD8; // Unlock protected register

author: james_s
author_rank: Super Contributor
timestamp: November 14, 2020, 03:04:15 am
content: Is there a reason that you're bothering with a watchdog timer on something that blinks a couple of LEDs? That's normally used to reset the processor if the code crashes so if it's doing something somewhat critical it doesn't get stuck in a bad state. With such a simple program it's hardly worth the bother.What I would suggest is first get the LEDs blinking with the code as minimal as possible, since you want to put the CPU to sleep between blinks you will probably want your main loop to be empty and just have the whole routine in the interrupt handler. Depending on the duty cycle of the LEDs and how bright you want them to be, you may find that the vast majority of the power is drawn by the LEDs themselves leaving little saved by using sleep. The sleep function is useful when you want to do something like wake up once every 15-60 seconds or so, do something for a few milliseconds like read a sensor and act on the result, then go back to sleep. Once you have an interrupt routine blinking to your liking you can try tweaks like turning off all the unused stuff and putting the core to sleep to save power. One step at a time.Also I haven't messed with the attiny4 specifically, but I've never done anything to change the CPU clock in the code itself, the clock speed and division factor on parts that support it are controlled by setting fusebits when you program the part. I think some do let you dynamically adjust it from the program but that shouldn't be necessary here, you can run it at 125kHz the whole time.

author: minipower
author_rank: Contributor
timestamp: November 14, 2020, 08:02:52 pm
content: The attiny4 datasheet says the sleep mode (power down) Can only wake up with INT0 and Pin change and the only timer running is the watchdog time.So I pretty much stood on the shoulders of others and copied what they did.I'm using the watchdog to wake up from sleep mode (power down) and to space out the short pause between the 2 blinking led's and the long pause before it starts over.As you said about the led power draw. I agree in think the led's will be the biggest power drain. I'm planing to experiment with led resistors, so I can dial in there brightness.After I get some experience with MCU's. I'm going to try to learn how to use the PWM to drive the led's.I did see using milliseconds to time the blink and pause. I'm not that good to pull it off yet. But would I still need a timer and a way to wake-up the cpu ?I think I found the correct way to set the cpu speed:// Clock division factor 256 (1000)CLKPSR=(1<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0);I believe this was the wrong way:CLKPSR=256; // Clock division factor 256 (1000)CKSEL=11I think these are the attiny configuration/fusebitsDisable external resetWatch dog timer always onOutput external clockDisable Reset Pin - Makes pin 6 into a output. But then you will have to use a High Voltage programmer to program the chip.

author: sleemanj
author_rank: Super Contributor
timestamp: November 14, 2020, 09:30:47 pm
content: This is how my arduino core for the 4/5/9/10 handles clock settinghttps://github.com/sleemanj/ATTinyCore/blob/5172add6ee7dc08432c51e3405c5424162924085/avr/variants/tiny4_9/pins_arduino.h#L134

author: minipower
author_rank: Contributor
timestamp: November 14, 2020, 10:18:40 pm
content: Oh. That shows me that I was closer to correct the 1st time " If closer to correct is a real thing "Am I understanding it right ?CCP = 0xD8; // Unlock protected registerCLKPSR = 8; // Clock division factor 256Plus I will need to put this before everything. So the compiler knows the cpu clock speed ¿#define F_CPU=31250Also I think the delay is wrong.incorrect.delay()Change to._delay_ms()

author: sleemanj
author_rank: Super Contributor
timestamp: November 15, 2020, 05:06:55 am
content: Quote from: minipower on November 14, 2020, 10:18:40 pmLong time since I wrote that so I had to have a look at the datasheet againYes to change CLKPSR or CLKMS you need to set CCP (configuration change protection) first and then the CLKPSR/MS can be changed for the next 4 clock cycles. See pages 22 (CCP), 34 (CLKMS) and 36 (CLKPSR).It looks like my code leaves the clock at the main 8MHz system clock and uses the prescaler to get the desired 128kHz, equally you could set the prescaler to no division (CLKPS=0) and set the system clock to use the WDT clock with CLKMS=1 the WDT clock will be less accurate but probably lower power. You can of course also go slower.You probably want to read about the Power Reduction Register from page 39 and about MInimizing Power Consumption from page 40

author: minipower
author_rank: Contributor
timestamp: November 16, 2020, 06:35:11 pm
content: I'm confused about a few things.I always thought the cpu speed and timer were 2 different things. One first would select the cpu speed and then choose a timer.The other is. I don't know how to do the math, of figuring out what the settings I choose equals the cpu speed, or how to reverse the math to work out the settings for the chosen cpu speed.The cpu speed and prescaler. It's not clicking. How does the prescaler work and what is it's function ?What setting makes the cpu faster or slower. I'm thinking a 0 makes the cpu faster and 256 makes it slower.After I did the changes pointed out and placing the missing ; I was able to build / compile it in Atmel studio 7. Except I do not have the correct watchdog timer "invoke"?. So I'm going to look at getting that right.I have this -- implicit declaration of function 'setup_watchdog' [-Wimplicit-function-declaration]setup_watchdog(9); // WDT prescale select 0-9// 0=16ms, 1=32ms, 2=64ms, 3=125ms, 4=250ms, 5=500ms// 6=1 sec, 7=2 sec, 8=4 sec, 9=8secand then 2 errors at the end --static declaration of '__vector_8' follows non-static declaration'WDTCR' undeclared (first use in this function)ISR (WDT_vect) {WDTCR |= _BV(WDIE);

author: james_s
author_rank: Super Contributor
timestamp: November 16, 2020, 06:46:56 pm
content: The clock that drives the CPU also drives the timer, and there is a selectable prescaler on it. For example if you set the CPU clock to 1MHz and select the prescaler to 128 then the timer will be clocked at 1MHz/128, about 8kHz. You can then set the timer to whatever value and it will increment or decrement at that rate. The timer is really just a counter that counts up or down at whatever clock rate you give it, and the starting value can be set to whatever you want and then it will trigger something when it reaches the end of its range.

author: minipower
author_rank: Contributor
timestamp: November 16, 2020, 07:02:05 pm
content: So the system clock is 1 thing and the prescaler chooses how accurate the timer is.So whatever system clock is chosen, you can tell the program to only count either all of the system clock ticks or every 256 system clock tick.The cpu is running the system clock speed but the timer will run slower ?The normal/regular system clock. Lowest speed is 1MHZ and using a prescaler just affects the timer. So the cpu is running at 1MHz.I have the choice to pick what the cpu uses as the system clock.1. normal system clock2. the slower low power watchdog timer3. external timerChoosing the 128kHz timer makes the cpu run at 128kHz and then if wanted, can make the timer less accurate by using the prescaler ?

author: sleemanj
author_rank: Super Contributor
timestamp: November 16, 2020, 08:13:43 pm
content: See page 29 of the datasheetYou can drive the system clock from the external, internal or the watchdog oscillator, the prescaler divides the selected clock down before using it.

author: james_s
author_rank: Super Contributor
timestamp: November 16, 2020, 08:17:05 pm
content: No, it's not accuracy, it's all about intervals and resolution. The longer interval you want to time, the slower you have to clock the timer. If you are dealing with a 16 bit timer then that means it is able to count up to 65,535 ticks before it reaches the end, like a stopwatch reaches an eventual limit of say 99 minutes, 99 seconds, 99 hundredths and stops because it is out of digits. If you clock the timer at 1MHz then the maximum period you can count for is about 15 seconds before the timer will overflow. If you want to measure a longer interval you have to clock the timer at a slower rate so you use the prescaler. Using that same example if you were to set a prescaler to /4 then the timer would be clocked at 250kHz and you could then measure an interval up to 60 seconds. The CPU clock controls how quickly the CPU executes instructions, the timer is an independent device that just happens to be driven by the same clock source, there is no reason you couldn't build a timer that has its own separate clock oscillator, there is just not really any good reason to do so.

author: sleemanj
author_rank: Super Contributor
timestamp: November 16, 2020, 08:18:44 pm
content: Quote from: minipower on November 16, 2020, 07:02:05 pmYou can make is slower using the prescaler. Prescaler = divider.If you choose 128kHz WDT osc as the input clock source, then apply a prescaler, you clock the system at between 128kHz (Prescaler = 0000) to 500Hz (Prescaler = 1000, 128kHz/256), see page 36 of the datasheet (and also pay attention to the paragraph on page 37)

author: minipower
author_rank: Contributor
timestamp: November 16, 2020, 09:14:58 pm
content: Ok. I think I'm getting it. My word accuracy = resolution.And the cpu - system clock is seperate from timer. And the cpu speed is governed by the system clock and if wanted, the prescaler . So1st is the system clock or which ever clock source chosen.2nd if wanted the prescaler - which divides the system clock which slows down the cpu speed3rd dividing the system clock by the prescaler = the cpu speed.I'm invisioning it like this.You have a gear 8 inchs in diam and you want to slow it down. You place a larger gear to be driven by the 1st smaller one.I'm guessing that its ok to really slow down the cpu to blink leds. But if I wanted to read - say - a temperature sensor, Not good. The slower the cpu the less precise the reading.pulling numbers out my butt.128KHz cpu speed = a temperature reading once a minute but speed up the cpu and I could get a reading once a second or even more per second.I will look over those sections and others. But now with the info you guyz have helped me figure out.

author: james_s
author_rank: Super Contributor
timestamp: November 17, 2020, 03:18:01 am
content: I'm not familiar with the attiny4 in particular but in many of these AVRs there are multiple prescalers, one for each timer, and one for the ADC. The internal block diagram of the chip is in the datasheet but in summary there is one master oscillator that can supply everything and then some of the fancier parts have a second low frequency 32kHz oscillator specifically for timekeeping. The CPU core is driven by the oscillator and in some cases has a rudimentary prescaler, usually with only two settings such as off or divide by 8. This controls the speed that the core executes code and the purpose of the slower speed is to reduce power power consumption.Peripherals that need a clock such as the timers and ADC each have their own prescaler, this is fed by either the same clock signal feeding the CPU core or by an external timer interrupt clock source. The prescalers for these peripherals are there to add flexibility for reasons already explained. A prescaler is just a divider, it lets you vary the speed that something operates without changing the speed of the oscillator itself which may be clocking multiple different things.You will need to sit down and study the datasheet to fully understand this stuff, it is all laid out pretty clearly in there.

author: minipower
author_rank: Contributor
timestamp: November 18, 2020, 10:56:08 pm
content: thank you guys. Your info is helping. I am having a little difficulty keeping track of all the chips functions and how they affect each other. That should just take time and working experience.I read that the slower the MCU runs, the slower the programming speed needs to be, about a quarter the speed of the MCU speed. Since the MCU uses software to set the operating perimeters, like speed and pins. If I run the MCU at 500hz would I need to also reduce the programming speed to about 100hz ?Or can the MCU be reset to default speed and catch the MCU before my settings take place, that will allow a faster programming speed ? Or would it be a good idea to put a 1 second delay at the top of my int main(void) ?Another unknown is the pin 6 reset pin. If I tell it to be a output, would that stop me from reprogramming it ? Or would that only be affected by the enabling the RSTDISBL fuse bit ? Meaning only high voltage programmer an do anything with the chip.If I'm able to set the pin 6 reset pin to output and still program it. I will be able to cut out a few lines of code, that set pins 4 & 6 to inputs and enabling the pull up resistors on them. And just use DDRB |= 0xFF to set all pins as outputs.Reading the datasheet. These are the security setting that either allows reading and writing without having to erase the chip. So as long as I don't accidentally copy and pastNVLB1 = 0NVLB2 = 0I will still be able to read and write to the MCU.Sorry about not putting the sections of the relevant datasheet. I have yet to figure out how to copy and paste them from the datasheet pdf to the forum.

author: sleemanj
author_rank: Super Contributor
timestamp: November 19, 2020, 02:26:35 am
content: To use the RESET pin as IO then reset must be disabled (fuse), if you disable reset then you can only program if you apply 12v to the reset pin during programming.I'm not 100% on the TPI speed, but I expect that TPI is done with respect to the default system clock, which is, 1MHz from memory (8 divide by. I couldn't quickly find any reference to the maximum recommended speed for TPI, 1/4 sysclock is true for SPI and I would guess that TPI the same.Similarly I can't readily see if reset on tinyAVR will reset the system clock registers (CLKPSR and CLKMS) or if they survive reset - I would guess that they get reset, but I wouldn't be certain.

author: james_s
author_rank: Super Contributor
timestamp: November 19, 2020, 03:56:49 am
content: I know with the attiny13 if you clock it really slow you have to dial down the programming speed. The programming interface is a glaring flaw in the otherwise excellent AVR microcontrollers, it's possible to brick the chip by selecting a clock mode that requires an external clock or crystal in a design that doesn't have one, or by disabling reset. It's a more than 20 year old design so I can't complain too much though, at the time it was somewhat revolutionary in that such simple and inexpensive hardware could be used to program it and the use of flash was really slick back then too. Most prior microcontrollers used EPROM and you either needed an expensive one with a quartz window for erasing or they were OTP.

author: minipower
author_rank: Contributor
timestamp: November 20, 2020, 11:09:34 pm
content: I'm stuck againWhen I 1st started playing with all this. I was using the Arduino IDE and a Digispark Attiny85 board.I worked out the timing to my satisfaction and was going to Port the code to the Attiny4. This is what I ended upo with in the Arduino IDECode:#include <avr/wdt.h>#include <avr/sleep.h>#include <avr/interrupt.h>#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off)//#define adc_enable() (ADCSRA |= (1<<ADEN)) // re-enable ADCvoid setup(){// Power Saving setupfor (byte i = 0; i < 6; i++) {pinMode(i, INPUT); // Set all ports as INPUT to save energydigitalWrite (i, LOW); //}adc_disable(); // Disable Analog-to-Digital Converterwdt_reset(); // Watchdog resetwdt_enable(WDTO_4S); // Watchdog enable Options: 15MS, 30MS, 60MS, 120MS, 250MS, 500MS, 1S, 2S, 4S, 8SWDTCR|= _BV(WDIE); // Interrupts watchdog enablesei(); // enable interruptsset_sleep_mode(SLEEP_MODE_PWR_DOWN); // Sleep Mode: max}void loop(){pinMode(1, OUTPUT);digitalWrite(1, HIGH); // 1 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msdigitalWrite(1, LOW); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msdigitalWrite(1, HIGH); // 2 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msdigitalWrite(1, LOW); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msdigitalWrite(1, HIGH); // 3 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msdigitalWrite(1, LOW); // turn the LED off by making the voltage LOW// adc_disable(); // Disable Analog-to-Digital Convertersleep_enable();sleep_cpu();digitalWrite(1, HIGH); // 1 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msdigitalWrite(1, LOW); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msdigitalWrite(1, HIGH); // 2 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msdigitalWrite(1, LOW); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msdigitalWrite(1, HIGH); // 3 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msdigitalWrite(1, LOW); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msdigitalWrite(1, HIGH); // 4 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msdigitalWrite(1, LOW); // turn the LED off by making the voltage LOWdelay(100); // wait for 100msdigitalWrite(1, HIGH); // 5 turn the LED on (HIGH is the voltage leveldelay(200); // wait for 200msdigitalWrite(1, LOW); // turn the LED off by making the voltage LOW// adc_disable(); // Disable Analog-to-Digital Convertersleep_enable();sleep_cpu();// adc_disable(); // Disable Analog-to-Digital Convertersleep_enable();sleep_cpu();}ISR (WDT_vect) {WDTCR |= _BV(WDIE);}Page 53 shows this.9 0x008 WDT Watchdog Time-out InterruptInstead of this.ISR (WDT_vect) {So I should put this ?ISR (WDT) {This is the jumbled mess I have so far.Code:/** 2 leds.c** Created: 11/10/2020 11:27:18 AM* Author : rascal*/#define F_CPU 500UL#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>#include <avr/wdt.h>#include <util/delay.h>#define RED PB0#define GREEN PB1int main(void){cli(); // Disable global interrupts before initializationCCP=0xD8; // Unlock protected registerCLKMSR=0x01; // Change clock source to Low-power 128 kHz oscillatorCLKPSR=0b1000; // Clock division factor 256 (1000) = 500HzPRR |= (1<<PRTIM0); // Turn timer0 offDDRB = 0b00000011; // Pins 4 & 6 inputs - Pins 1 & 3 outputsPUEB = (1<<PUEB2)|(1<<PUEB3); // Enable Pullup Resistor Pins 4 & 6ACSR = (1<<ACD); // Turn off Analog comparatorset_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set hereMCUSR = 0; // Clear MCU Status RegisterWDTON = (0<<WDE)|(1<<WDIE) ; //set watchdog in interrupt modewdt_reset(); // Watchdog resetWDP = 0b1001; // WDT prescale// 0000=16ms, 0001=32ms, 0010=64ms, 0011=125ms, 0100=250ms, 0101=500ms// 0110=1 sec, 0111=2 sec, 1000=4 sec, 1001=8sec//wdt_enable(WDP=1001); // Watchdog enable Options: 15MS, 30MS, 60MS, 120MS, 250MS, 500MS, 1S, 2S, 4S, 8SWDTCR|= _BV(WDIE); // Interrupts watchdog enablesei(); // enable interruptsSMCR = (1<<SE); //enable power-down sleep modesei(); //initialize global interrupts before beginning loop/* Replace with your application code */while (1){// Blink PB0 (RED led) 4 times then sleepPORTB |=(1<<RED); // 1 turn the LED on (HIGH is the voltage level_delay_ms(200); // wait for 200msPORTB &=~(1<<RED); // turn the LED off by making the voltage LOW_delay_ms(100); // wait for 100msPORTB |=(1<<RED); // 1 turn the LED on (HIGH is the voltage level_delay_ms(200); // wait for 200msPORTB &=~(1<<RED); // turn the LED off by making the voltage LOW_delay_ms(100); // wait for 100msPORTB |=(1<<RED); // 1 turn the LED on (HIGH is the voltage level_delay_ms(200); // wait for 200msPORTB &=~(1<<RED); // turn the LED off by making the voltage LOWsleep_enable();sleep_cpu(); //sleep// Blink PB0 (GREEN led) 5 times then sleepPORTB |=(1<<GREEN); // 1 turn the LED on (HIGH is the voltage level_delay_ms(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOW_delay_ms(100); // wait for 100msPORTB |=(1<<GREEN); // 2 turn the LED on (HIGH is the voltage level_delay_ms(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOW_delay_ms(100); // wait for 100msPORTB |=(1<<GREEN); // 3 turn the LED on (HIGH is the voltage level_delay_ms(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOW_delay_ms(100); // wait for 100msPORTB |=(1<<GREEN); // 4 turn the LED on (HIGH is the voltage level_delay_ms(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOW_delay_ms(100); // wait for 100msPORTB |=(1<<GREEN); // 5 turn the LED on (HIGH is the voltage level_delay_ms(200); // wait for 200msPORTB &=~(1<<GREEN); // turn the LED off by making the voltage LOWsleep_enable(); // 2 sleep modes to extend the (pause) not blinking timesleep_cpu();sleep_enable(); // 2 sleep modes to extend the (pause) not blinking timesleep_cpu();}// Watchdog Interrupt Service / is executed when watchdog timed outISR(WDT_vect) {// f_wdt=1; // set global flagWDTCR |= (1<<WDIE);}}These are the build errors I'm getting in Atmelstudio 7recipe for target 'main.o' failed'MCUSR' undeclared (first use in this function)'WDTON' undeclared (first use in this function)'WDP' undeclared (first use in this function)'WDTCR' undeclared (first use in this function)static declaration of '__vector_8' follows non-static declarationI'm stuck at setting the Watchdog timer Prescaler.Because of the build errors I'm getting. I'm guessing this is an Arduino thing and not used in AtmelStudio gcc.wdt_enable(WDTO_4S); // Watchdog enable Options: 15MS, 30MS, 60MS, 120MS, 250MS, 500MS, 1S, 2S, 4S, 8SSamething here. Or is this a Attiny85 setting and is different on the Attiny4 ?}ISR (WDT_vect) {WDTCR |= _BV(WDIE);}It seems 1 of my issues in understanding what to type for the setting I'm trying to use.Like this. On page 50, the datasheet saysBits 5,2:0 – WDPn: Watchdog Timer Prescaler [n=3:0]The WDP[3:0] bits determine the Watchdog Timer prescaling when the Watchdog Timer is running. Thedifferent prescaling values and their corresponding time-out periods are shown in the table below.If your able to see the changes I have been trying in the Atmel studio code. I'm not understang what I need to plug, that will chose my wanted settings.Or is there a #include I can use, that allow me to use the Arduino IDE in the AtmelStudio ?I apologize for the messy code. I have been trying to keep myself to 1 change at a time, so I can keep track of what is really working and what is not.

author: sleemanj
author_rank: Super Contributor
timestamp: November 21, 2020, 12:06:31 am
content: In regards your Arduino sketch,* Tiny 4 does not have ADC, so ADCSRA does not exist and the adc functions are invalid* Tiny 4 has WDTCSR instead of WDTCRRemoving the adc stuff and changing the register name to WDTCSR allows your Arduino sketch to compile for ATTiny4 using my 2020.10.10 version of DIY ATtiny Arduino Core selected for Tiny 4. It's too big (Sketch uses 570 bytes (111%) of program storage space. Maximum is 512 bytes.), but it compiles. If you lose the "power saving setup" loop then you can compile with room to spare. Since they are all being set INPUT LOW anyway that should be the default so no need for it.https://github.com/sleemanj/optiboot/blob/master/dists/README.md#attiny4-attiny5-attiny9-attiny10---Generally speaking ATtiny4 and Attiny85 are two very different chips and have different registers, for an example in your code it does not have an MCUSR which is where the T85 indicates the reset source, the T4 has a RSTFLR register bit 3 of which is WDRF and indicates if the reset was because of WDT, page 52.WDT_vect is the correct vector name, which you can see in iotn4.h of your installation....Code:$ cat iotn4.h | grep WDT#define WDTCSR _SFR_IO8(0x31)#define WDT_vect_num 8#define WDT_vect _VECTOR(8) /* Watchdog Time-out */If you have written for the T85 I would suggest you are better to either stick with the x5 series or go to Tiny13 which is mostly the same just with 1k flash.

author: minipower
author_rank: Contributor
timestamp: November 21, 2020, 04:12:46 am
content: Yes. That is what I'm not able to do yet. Looking at code for different MCU's and being able to know what it equals to other MCU's.different registers.Tiny 4 has WDTCSR instead of WDTCRT85 MCUSR is the T4 RSTFLRLearning to understand and how to type out " correct syntax " the settingsShould I type thisRSTFLR=0; // Clear MCU Status Registerinstead ofMCUSR = 0; // Clear MCU Status RegisterAnd type this to turn on the watchdog timer as a InterruptWDTCSR = (0<<WDE)|(1<<WDIE) ; // set watchdog in interrupt modepage 49 Watchdog Timer Control RegisterTable 9-2. Watchdog Timer Configuration tableI'm guessing it should be something like thisWDTON = (0<<WDE) | (1<< WDIE) | (??But looking at other code, it should be; setup watchdogldi temp, 0xD8 ; write signatureout CCP, templdi temp, (0<<WDE)|(1<<WDIE)|(1<<WDP0) ; set watchdog in interrupt mode and 4k cyclesout WDTCSR, tempWDTCSR = (0<<WDE) | (1<<WDIE) | ( Again I don't understand what to put her for 8 seconds )I'm not understanding what WDP[3:0] means so I know what to put in the last ( )Like this page 50 WDPn: Watchdog Timer Prescaler [n=3:0] WDP[3:0]It makes me think this is how I should write itWDP = 1001orWDTCSR = (0<<WDE) | (1<<WDIE) | (1<<WDP0) | (0<<WDP1) | (0<<WDP2) | (1<<WDP3)The 4 biniary WDP=1001 is the 4 WDPn registers ?Maybe I should write itWDTCSR = (0<<WDE) | (1<<WDIE) | (1<<WDP0) | (1<<WDP3)Leaving out the 0's (0<<WDP1) | (0<<WDP2) because they are default 0. why tell a 0 to change to a 0. If it's already a 0 ?Another thing. Would setting the WDTON configuration bit make the code any smaller ? Since the WDTON flag is watchdog timer always on ?Sorry for the incorrect terms.Man this is frustrating. I can look at mechanical things and figure out how it is working and what the names of the parts are. But looking at code is a whole new thing. I can see the mechanical with my eyes and almost work it out. This is more about using my minds eyes to connect how the words / terms are connecting with all the rest. I guess I also use my minds eye to work out mechanical, but having years experience makes it feel so naturally intuitive.

author: minipower
author_rank: Contributor
timestamp: November 21, 2020, 04:46:18 am
content: Quote from: minipower on November 21, 2020, 04:12:46 am

author: sleemanj
author_rank: Super Contributor
timestamp: November 21, 2020, 06:50:30 am
content: As I aleady said, your arduino code compiles fine for tiny4 with the modifications given, not tested but it looks like it would probably function correctly, and the WD aspect of it is pure AVR c with no arduinoism i think if You really don't want to code in Arduino.As for the rest of your post that comes down ti "read and understand the datasheet", not just copy code without knowing what it dooes, for example you ask "Should I type this RSTFLR=0; // Clear MCU Status Register instead of MCUSR = 0; // Clear MCU Status Registe" well ask yourself what you are trying to achieve, if you don't understand **why** it is being done, then thats what you need to figure out. and it's in the datasheet, hint, see the note about WE and how WDRF overrides it.

author: admiralk
author_rank: Regular Contributor
timestamp: November 22, 2020, 02:30:57 am
content: Quote from: sleemanj on November 21, 2020, 06:50:30 amThis should have been in the first reply. When you walk away from Arduino you no longer have the luxury of everything being the same.

author: minipower
author_rank: Contributor
timestamp: November 22, 2020, 04:45:11 am
content: I totally agree. Reading and understanding are 2 different things. I'm trying to change the settings to see what it does. Trying to put the different code types and mcu's in context with what I'm reading in the datasheet.I ran across CodeVison AVR. It has CodeWizard AVR. You can choose the mcu and its options and it will set up the code for you, then you would put your program code in the locations.It is helping me see and understand how the different mcu options code should be written.sleemanj I did look at and try to play around with your IDE. I like it. At the bottom of your git readme, it talks about saving to the eeprom, as an option now or the future. Would that allow me place the mcu power saving setup inside to free up space. Calling for it when needed ?

author: james_s
author_rank: Super Contributor
timestamp: November 22, 2020, 05:08:53 am
content: Focus on the part of the datasheet that explains what all of the registers do, then when you want more details about a specific register, go look at the section on the peripheral that it controls. The datasheet explains exactly what registers there are and what each bit in these registers controls.

author: sleemanj
author_rank: Super Contributor
timestamp: November 22, 2020, 06:52:53 am
content: Quote from: minipower on November 22, 2020, 04:45:11 amNo.

author: minipower
author_rank: Contributor
timestamp: December 05, 2020, 12:11:21 am
content: With your guyz help and being able to look at how the coding is suppose to look like by using CodeVisionAVR. I was able to understand the datasheet more and how to write the settings I wanted.I have been able to get a program the builds without errors. My goal was to write a small lean program without unneeded bloat. I'm getting pretty close.Here is what I have so farCode:/** 5-7 256 WDP 2s.c* Author : rascal*/#define F_CPU 1000UL#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>#include <avr/wdt.h>#include <util/delay.h>EMPTY_INTERRUPT(WDT_vect) //clearing the interrupt flagint main(void){cli(); // Disable global interrupts before initializationCCP=0xD8; // Unlock protected registerCLKMSR=(0<<CLKMS1) | (1<<CLKMS0); // Change clock source to Low-power 128 kHz oscillatorCCP=0xd8;CLKPSR=(1<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0); // Clock division factor 256PRR = (1<<PRTIM0); // Turn timer0 offDDRB = 0b00001111; // Pins 1 - 3 - 5 - 6 outputs//PUEB = (1<<PUEB3); // Enable Pull up Resistor Pin 6ACSR = (1<<ACD); // Turn off Analog comparatorCCP=0xd8;// Watch dog timer prescaler = 2.0sWDTCSR=(1<<WDIF) | (1<<WDIE) | (0<<WDP3) | (0<<WDE) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0);VLMCSR=(0<<VLMF) | (0<<VLMIE) | (0<<VLM2) | (0<<VLM1) | (0<<VLM0); // Trigger Level: Voltage Level Monitor Disabledset_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set heresleep_enable();wdt_reset(); // Watchdog resetsei(); //initialize global interrupts before beginning loopwhile (1) {// Blink PB0 (Pin 1 RED led) 5 times then sleepPORTB |=(1<<PB0); // 1 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB0); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150msPORTB |=(1<<PB0); // 2 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB0); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150msPORTB |=(1<<PB0); // 3 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB0); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 250msPORTB |=(1<<PB0); // 4 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB0); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150msPORTB |=(1<<PB0); // 5 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB0); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150mssleep_enable(); // sleep mode to extend the (pause) between blinking timesleep_cpu();// Blink PB0 (Pin 2 GREEN led) 7 times then sleepPORTB |=(1<<PB1); // 1 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB1); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150msPORTB |=(1<<PB1); // 2 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB1); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150msPORTB |=(1<<PB1); // 3 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB1); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150msPORTB |=(1<<PB1); // 4 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB1); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150msPORTB |=(1<<PB1); // 5 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB1); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150msPORTB |=(1<<PB1); // 6 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB1); // turn the LED off by making the voltage LOW_delay_ms(150); // wait for 150msPORTB |=(1<<PB1); // 7 turn the LED on (HIGH is the voltage level_delay_ms(250); // wait for 250msPORTB &=~(1<<PB1); // turn the LED off by making the voltage LOW_delay_ms(250); // wait for 250mssleep_enable(); // 2 sleep modes to extend the (pause) not blinking timesleep_cpu();sleep_enable(); // 2 sleep modes to extend the (pause) not blinking timesleep_cpu();}// Watchdog Interrupt Service / is executed when watchdog timed outISR(WDT_vect);}Question. Since I'm using the WDT and not the main system clock, can I take this out ?CLKPSR=(1<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0); // Clock division factor 256To me, it would seem unneeded. And I get error if I don't put a ; here}// Watchdog Interrupt Service / is executed when watchdog timed outISR(WDT_vect);}I see others not have the ;One thing all this has taught me is that I magic powers.. The hex files generated are from 700 - 990 bytes but only write a little more than half of that to the chip and it works.Also, I have been able to write to the chip at the highest speed no matter how slow the mcu is clocked at. I guess, since the mcu speed it set in the code, when the mcu is reset and written to, it defaults to the default speed.

author: james_s
author_rank: Super Contributor
timestamp: December 05, 2020, 02:57:51 am
content: The hex files contain a bunch of overhead that is used to package the data to be written to the chip, it will always be larger than the actual program. If you set the compiler to output a .bin file that should be exactly the same size as the flash that it will be written to.

author: minipower
author_rank: Contributor
timestamp: January 10, 2021, 03:26:16 am
content: sleemanj -- Trying to copy and paste the code from atmel studio 7 to ATTINY10IDEI assume this error is a problem with my computers installed java. Before I try. Would uninstall and reinstalling java fix it ¿Code:os.name: windows 7os: WINsrcZip: toolchains/WinToolchain.zipStack Trace:java.lang.StringIndexOutOfBoundsException: String index out of range: -1at java.lang.String.substring(Unknown Source)at ATTinyC.lambda$null$11(ATTinyC.java:576)at java.lang.Thread.run(Unknown Source)

author: sleemanj
author_rank: Super Contributor
timestamp: January 10, 2021, 08:27:01 am
content: Quote from: minipower on January 10, 2021, 03:26:16 amI do not use either

author: minipower
author_rank: Contributor
timestamp: January 10, 2021, 02:59:29 pm
content: Oops .. embarrassingI mixed up ATTiny10IDE and your core.