<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://www.marcelpost.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Tips_n_Tricks</id>
	<title>Tips n Tricks - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.marcelpost.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Tips_n_Tricks"/>
	<link rel="alternate" type="text/html" href="https://www.marcelpost.com/wiki/index.php?title=Tips_n_Tricks&amp;action=history"/>
	<updated>2026-06-16T20:25:10Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://www.marcelpost.com/wiki/index.php?title=Tips_n_Tricks&amp;diff=3204&amp;oldid=prev</id>
		<title>Admin at 04:19, 17 November 2019</title>
		<link rel="alternate" type="text/html" href="https://www.marcelpost.com/wiki/index.php?title=Tips_n_Tricks&amp;diff=3204&amp;oldid=prev"/>
		<updated>2019-11-17T04:19:07Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Here&amp;#039;s a compilation of various tips and tricks I came across over the years. Feel free to use and re-use as much as you like.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==set, clear and toggle macros==&lt;br /&gt;
&lt;br /&gt;
With AVR micros an often cryptic method is used to set, clear or toggle bits. Take for instance the following example to set a digital port to output and set it to a digital &amp;#039;1&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#DEFINE LEDPIN PB0        // define LED pin&lt;br /&gt;
&lt;br /&gt;
DDRB |= (1 &amp;lt;&amp;lt; LEDPIN);    // set to output&lt;br /&gt;
&lt;br /&gt;
PORTB |= (1 &amp;lt;&amp;lt; LEDPIN);   // write a digital &amp;#039;1&amp;#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With these macros writing a digital &amp;#039;1&amp;#039; is now as simple as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Some helper MACROS&lt;br /&gt;
#define SET |=&lt;br /&gt;
#define CLR &amp;amp;=~&lt;br /&gt;
#define TOG ^=&lt;br /&gt;
&lt;br /&gt;
#DEFINE LEDPIN PB0         // define LED pin&lt;br /&gt;
&lt;br /&gt;
DDRB SET (1 &amp;lt;&amp;lt; LEDPIN);    // set to output&lt;br /&gt;
&lt;br /&gt;
PORTB SET (1 &amp;lt;&amp;lt; LEDPIN);   // write a digital &amp;#039;1&amp;#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==bitwise operations==&lt;br /&gt;
&lt;br /&gt;
Similar to the above, here are some commands to set, clear or toggle a specific bit:&lt;br /&gt;
&lt;br /&gt;
* set (to 1) bit 2 (the third bit from the right) of variable a&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a |= (1&amp;lt;&amp;lt;2);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* clear (to 0) bit 2 (the third bit from the right) of variable a&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a &amp;amp;= ~(1&amp;lt;&amp;lt;2);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* toggle bit 2 (the third bit from the right) of variable a&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a ^= (1&amp;lt;&amp;lt;2);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Below is a set of macros that works with ANSI C to do bit operations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define bit_get(p,m) ((p) &amp;amp; (m))&lt;br /&gt;
#define bit_set(p,m) ((p) |= (m))&lt;br /&gt;
#define bit_clear(p,m) ((p) &amp;amp;= ~(m))&lt;br /&gt;
#define bit_flip(p,m) ((p) ^= (m))&lt;br /&gt;
#define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))&lt;br /&gt;
#define BIT(x) (0x01 &amp;lt;&amp;lt; (x))&lt;br /&gt;
#define LONGBIT(x) ((unsigned long)0x00000001 &amp;lt;&amp;lt; (x))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==byte type==&lt;br /&gt;
&lt;br /&gt;
In some programming environments the &amp;#039;byte&amp;#039; type is readily available. It&amp;#039;s usually just an unsigned char but if you don&amp;#039;t want to search-and-replace every instance of byte with unsigned char in your code then here&amp;#039;s a simple type definition that creates the byte type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef unsigned char byte; //create byte type&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==rounding and decimals==&lt;br /&gt;
&lt;br /&gt;
Float values sometimes have too many decimals. Here are some generic rounding formulas:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fl =  (int) (fl + 0.5f)/1.0f;            // round to 0 decimals&lt;br /&gt;
fl =  (int) (fl * 10 + 0.5f)/10.0f;      // round to 1 decimals&lt;br /&gt;
fl =  (int) (fl * 100 + 0.5f)/100.0f;    // round to 2 decimals&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==AVR Sleep Mode==&lt;br /&gt;
&lt;br /&gt;
A recent project I built using an ATtiny85 micro was working fine and using about 4mA in idle mode. The circuit and its peripherals were powered through a 78L05 so I was wondering by how much I could lower the current draw by using the sleep function of the micro.&lt;br /&gt;
&lt;br /&gt;
Here&amp;#039;s how I configured sleep mode to bring the current draw down to 2.4mA. This suggests that the voltage regulator still takes some energy to run at very low levels..&lt;br /&gt;
&lt;br /&gt;
The technique below uses the expiry of the on-board watchdog timer to generate an interrupt which wakes the micro. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 1 - import the sleep, watchdog and interrupt libraries&lt;br /&gt;
&lt;br /&gt;
Location: at the top of your code&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 2 - add some helper functions&lt;br /&gt;
&lt;br /&gt;
Location: above the main() block&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* NOTES:&lt;br /&gt;
 &lt;br /&gt;
                            ATtiny85   ATtiny84&lt;br /&gt;
  Watchdog Timer Register:   WDTCR      WDTCSR&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void wdtEnable(void)&lt;br /&gt;
{&lt;br /&gt;
    wdt_reset();&lt;br /&gt;
    cli();&lt;br /&gt;
    MCUSR = 0x00;&lt;br /&gt;
    WDTCR |= _BV(WDCE) | _BV(WDE);    &lt;br /&gt;
    WDTCR = _BV(WDIE) | _BV(WDP2); // 250ms&lt;br /&gt;
    sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//disable the wdt&lt;br /&gt;
void wdtDisable(void)&lt;br /&gt;
{&lt;br /&gt;
    wdt_reset();&lt;br /&gt;
    cli();&lt;br /&gt;
    MCUSR = 0x00;&lt;br /&gt;
    WDTCR |= _BV(WDCE) | _BV(WDE);&lt;br /&gt;
    WDTCR = 0x00;&lt;br /&gt;
    sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void system_sleep() &lt;br /&gt;
{&lt;br /&gt;
		ACSR |= _BV(ACD); //disable the analog comparator&lt;br /&gt;
        ADCSRA &amp;amp;= ~_BV(ADEN); //disable ADC&lt;br /&gt;
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
        sleep_enable();&lt;br /&gt;
        wdtEnable(); //start the WDT &lt;br /&gt;
        //turn off the brown-out detector.&lt;br /&gt;
        //must have an ATtiny45 or ATtiny85 rev C or later for software to be able to disable the BOD.&lt;br /&gt;
        //current while sleeping will be &amp;lt;0.5uA if BOD is disabled, &amp;lt;25uA if not.&lt;br /&gt;
        cli();&lt;br /&gt;
        mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector&lt;br /&gt;
        mcucr2 = mcucr1 &amp;amp; ~_BV(BODSE);&lt;br /&gt;
        MCUCR = mcucr1;&lt;br /&gt;
        MCUCR = mcucr2;&lt;br /&gt;
        sei(); //ensure interrupts enabled so we can wake up again&lt;br /&gt;
        sleep_cpu(); //go to sleep&lt;br /&gt;
                                       //----zzzz----zzzz----zzzz----zzzz&lt;br /&gt;
        cli(); //wake up here, disable interrupts        &lt;br /&gt;
        sleep_disable();&lt;br /&gt;
        wdtDisable(); //don&amp;#039;t need the watchdog while we&amp;#039;re awake&lt;br /&gt;
        sei(); //enable interrupts again (but INT0 is disabled above)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// insert the ISR function outside the main() loop, all the way at the bottom of the code&lt;br /&gt;
ISR(WDT_vect) {} //don&amp;#039;t need to do anything here when the WDT wakes the MCU&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 3 - insert code to configure the sleep/watchdog registers once at startup&lt;br /&gt;
 &lt;br /&gt;
Location: at the top of the main() block&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wdt_reset();&lt;br /&gt;
wdtDisable();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 4 - add your sleep command at the idle position(s)&lt;br /&gt;
&lt;br /&gt;
Location: normaly where you would have a delay at the end of a loop in main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
system_sleep();		&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Step 5 - disable BOD in the command to flash the code to the micro or in software (not all models supported!)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-U hfuse:w:0xDF:m &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==custom functions and libraries==&lt;br /&gt;
&lt;br /&gt;
Here&amp;#039;s a simple function that makes it easy to blink out a value. Handy if you only have one LED as a means for feedback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// With this code, a value like 302 is blinked as:&lt;br /&gt;
//&lt;br /&gt;
//   &amp;lt;short&amp;gt; &amp;lt;short&amp;gt; &amp;lt;short&amp;gt;      &amp;lt;long&amp;gt;      &amp;lt;short&amp;gt; &amp;lt;short&amp;gt;     &lt;br /&gt;
&lt;br /&gt;
void shortblink(uint8_t ledpin)&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(ledpin,HIGH);&lt;br /&gt;
  _delay_ms(50);&lt;br /&gt;
  digitalWrite(ledpin,LOW);&lt;br /&gt;
  _delay_ms(500);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void longblink(uint8_t ledpin)&lt;br /&gt;
{&lt;br /&gt;
  digitalWrite(ledpin,HIGH);&lt;br /&gt;
  _delay_ms(600);&lt;br /&gt;
  digitalWrite(ledpin,LOW);&lt;br /&gt;
  _delay_ms(500);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void numberblink(uint16_t value, uint8_t ledpin)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
  // blinks a number (from 0 - 65535) to a LED&lt;br /&gt;
&lt;br /&gt;
  uint16_t divisor = 10000;&lt;br /&gt;
  uint8_t blinked=0;&lt;br /&gt;
   &lt;br /&gt;
  while (divisor &amp;gt;= 10)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    if (value &amp;gt; divisor)&lt;br /&gt;
    {&lt;br /&gt;
      // do some blinking&lt;br /&gt;
      while (value &amp;gt;= divisor)&lt;br /&gt;
      {&lt;br /&gt;
&lt;br /&gt;
        shortblink(ledpin);&lt;br /&gt;
        blinked=1;&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;gt;= divisor)&lt;br /&gt;
          value = value - divisor;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // value is less than divisor, probably encountered a (middle) zero&lt;br /&gt;
      // blink long if we&amp;#039;ve blinked before&lt;br /&gt;
      if (blinked == 1)&lt;br /&gt;
        longblink(ledpin);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _delay_ms(1000);&lt;br /&gt;
    divisor = divisor / 10;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (value == 0)&lt;br /&gt;
  {&lt;br /&gt;
    // always long blink last zero&lt;br /&gt;
    longblink(ledpin);&lt;br /&gt;
&lt;br /&gt;
  } else {&lt;br /&gt;
&lt;br /&gt;
    while (0 &amp;lt; value)&lt;br /&gt;
    {&lt;br /&gt;
      // blink ones&lt;br /&gt;
      shortblink(ledpin);&lt;br /&gt;
      value=value-1;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>