<![CDATA[TechBitar - Blog]]>Wed, 03 Feb 2016 21:07:27 -0800EditMySite<![CDATA[The Assembly Code for Arduino's Blink Example]]>Thu, 17 Apr 2014 16:19:17 GMThttp://www.techbitar.com/blog/the-assembly-code-for-arduinos-blink-exampleThe amount of behind the scenes work performed to make the Arduino IDE a friendly tool is amazing. As an example, this is the Arduino Blink demo code bundled in the IDE version 1.05 and below is the generated assembly code.

To view the generated assembly code by your Arduino IDE for your sketches follow the instructions in this guide
Code Editor
This is the assembly code generated by the Arduino IDE 1.05 for Arduino Uno (atmega328p) 
Disassembly of section .text:00000000 <__vectors>:        timer0_millis = m;        timer0_overflow_count++;}unsigned long millis(){   0:        0c 94 61 00         jmp     0xc2     ; 0xc2 <__ctors_end>        SREG = oldSREG;}int digitalRead(uint8_t pin){   4:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>   8:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>   c:    0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  10:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  14:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  18:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  1c:     0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  20:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  24:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  28:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  2c:     0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  30:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  34:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  38:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  3c:     0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  40:        0c 94 9d 00         jmp     0x13a    ; 0x13a <__vector_16>  44:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  48:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  4c:     0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  50:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  54:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  58:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  5c:     0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  60:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>  64:        0c 94 7e 00         jmp     0xfc     ; 0xfc <__bad_interrupt>00000068 <port_to_mode_PGM>:  68:        00 00 00 00 24 00 27 00 2a 00                       ....$.'.*.00000072 <port_to_output_PGM>:  72:        00 00 00 00 25 00 28 00 2b 00                       ....%.(.+.0000007c <port_to_input_PGM>:  7c:     00 00 00 00 23 00 26 00 29 00                       ....#.&.).00000086 <digital_pin_to_port_PGM>:  86:        04 04 04 04 04 04 04 04 02 02 02 02 02 02 03 03     ................  96:        03 03 03 03                                         ....0000009a <digital_pin_to_bit_mask_PGM>:  9a:     01 02 04 08 10 20 40 80 01 02 04 08 10 20 01 02     ..... @...... ..  aa:    04 08 10 20                                         ... 000000ae <digital_pin_to_timer_PGM>:  ae:    00 00 00 07 00 02 01 00 00 03 04 06 00 00 00 00     ................  be:    00 00 00 00                                         ....000000c2 <__ctors_end>:  c2:    11 24             eor     r1, r1  c4:    1f be            out     0x3f, r1 ; 63  c6:    cf ef           ldi     r28, 0xFF        ; 255  c8:    d8 e0           ldi     r29, 0x08        ; 8  ca:    de bf           out     0x3e, r29        ; 62  cc:    cd bf           out     0x3d, r28        ; 61000000ce <__do_copy_data>:  ce:    11 e0            ldi     r17, 0x01        ; 1  d0:    a0 e0           ldi     r26, 0x00        ; 0  d2:    b1 e0           ldi     r27, 0x01        ; 1  d4:    ea e3           ldi     r30, 0x3A        ; 58  d6:    f4 e0           ldi     r31, 0x04        ; 4  d8:    02 c0            rjmp    .+4          ; 0xde <.do_copy_data_start>000000da <.do_copy_data_loop>:  da:    05 90             lpm     r0, Z+  dc:    0d 92             st      X+, r0000000de <.do_copy_data_start>:  de:    a2 30            cpi     r26, 0x02        ; 2  e0:    b1 07            cpc     r27, r17  e2:    d9 f7           brne    .-10         ; 0xda <.do_copy_data_loop>000000e4 <__do_clear_bss>:  e4:    11 e0            ldi     r17, 0x01        ; 1  e6:    a2 e0           ldi     r26, 0x02        ; 2  e8:    b1 e0           ldi     r27, 0x01        ; 1  ea:    01 c0            rjmp    .+2          ; 0xee <.do_clear_bss_start>000000ec <.do_clear_bss_loop>:  ec:    1d 92             st      X+, r1000000ee <.do_clear_bss_start>:  ee:    ab 30            cpi     r26, 0x0B        ; 11  f0:    b1 07            cpc     r27, r17  f2:    e1 f7           brne    .-8          ; 0xec <.do_clear_bss_loop>  f4:    0e 94 0c 02         call    0x418    ; 0x418 <main>  f8:    0c 94 1b 02         jmp     0x436    ; 0x436 <_exit>000000fc <__bad_interrupt>:  fc:    0c 94 00 00         jmp     0        ; 0x0 <__vectors>00000100 <loop>: 100:        80 91 00 01         lds     r24, 0x0100 104:        61 e0            ldi     r22, 0x01        ; 1 106:        0e 94 b8 01        call    0x370    ; 0x370 <digitalWrite> 10a:     68 ee            ldi     r22, 0xE8        ; 232 10c:     73 e0            ldi     r23, 0x03        ; 3 10e:     80 e0            ldi     r24, 0x00        ; 0 110:        90 e0            ldi     r25, 0x00        ; 0 112:        0e 94 e5 00        call    0x1ca    ; 0x1ca <delay> 116:        80 91 00 01         lds     r24, 0x0100 11a:     60 e0            ldi     r22, 0x00        ; 0 11c:     0e 94 b8 01        call    0x370    ; 0x370 <digitalWrite> 120:        68 ee            ldi     r22, 0xE8        ; 232 122:        73 e0            ldi     r23, 0x03        ; 3 124:        80 e0            ldi     r24, 0x00        ; 0 126:        90 e0            ldi     r25, 0x00        ; 0 128:        0e 94 e5 00        call    0x1ca    ; 0x1ca <delay> 12c:     08 95             ret0000012e <setup>: 12e:     80 91 00 01         lds     r24, 0x0100 132:        61 e0            ldi     r22, 0x01        ; 1 134:        0e 94 79 01         call    0x2f2    ; 0x2f2 <pinMode> 138:        08 95             ret0000013a <__vector_16>:#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)ISR(TIM0_OVF_vect)#elseISR(TIMER0_OVF_vect)#endif{ 13a:     1f 92             push    r1 13c:     0f 92             push    r0 13e:     0f b6            in      r0, 0x3f ; 63 140:        0f 92             push    r0 142:        11 24             eor     r1, r1 144:        2f 93             push    r18 146:        3f 93             push    r19 148:        8f 93             push    r24 14a:     9f 93             push    r25 14c:     af 93            push    r26 14e:     bf 93            push    r27        // 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 = timer0_millis; 150:        80 91 06 01         lds     r24, 0x0106 154:        90 91 07 01         lds     r25, 0x0107 158:        a0 91 08 01        lds     r26, 0x0108 15c:     b0 91 09 01        lds     r27, 0x0109        unsigned char f = timer0_fract; 160:        30 91 0a 01         lds     r19, 0x010A        m += MILLIS_INC; 164:        01 96             adiw    r24, 0x01        ; 1 166:        a1 1d            adc     r26, r1 168:        b1 1d            adc     r27, r1        f += FRACT_INC; 16a:     23 2f             mov     r18, r19 16c:     2d 5f             subi    r18, 0xFD        ; 253        if (f >= FRACT_MAX) { 16e:     2d 37             cpi     r18, 0x7D        ; 125 170:        20 f0            brcs    .+8          ; 0x17a <__vector_16+0x40>                f -= FRACT_MAX; 172:        2d 57             subi    r18, 0x7D        ; 125                m += 1; 174:        01 96             adiw    r24, 0x01        ; 1 176:        a1 1d            adc     r26, r1 178:        b1 1d            adc     r27, r1        }        timer0_fract = f; 17a:     20 93 0a 01         sts     0x010A, r18        timer0_millis = m; 17e:     80 93 06 01         sts     0x0106, r24 182:        90 93 07 01         sts     0x0107, r25 186:        a0 93 08 01        sts     0x0108, r26 18a:     b0 93 09 01        sts     0x0109, r27        timer0_overflow_count++; 18e:     80 91 02 01         lds     r24, 0x0102 192:        90 91 03 01         lds     r25, 0x0103 196:        a0 91 04 01        lds     r26, 0x0104 19a:     b0 91 05 01        lds     r27, 0x0105 19e:     01 96             adiw    r24, 0x01        ; 1 1a0:     a1 1d            adc     r26, r1 1a2:     b1 1d            adc     r27, r1 1a4:     80 93 02 01         sts     0x0102, r24 1a8:     90 93 03 01         sts     0x0103, r25 1ac:     a0 93 04 01        sts     0x0104, r26 1b0:     b0 93 05 01        sts     0x0105, r27} 1b4:     bf 91            pop     r27 1b6:     af 91            pop     r26 1b8:     9f 91             pop     r25 1ba:     8f 91             pop     r24 1bc:     3f 91             pop     r19 1be:     2f 91             pop     r18 1c0:     0f 90             pop     r0 1c2:     0f be            out     0x3f, r0 ; 63 1c4:     0f 90             pop     r0 1c6:     1f 90             pop     r1 1c8:     18 95             reti000001ca <delay>:                return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());}void delay(unsigned long ms){ 1ca:     9b 01             movw    r18, r22 1cc:     ac 01            movw    r20, r24        return m;}unsigned long micros() {        unsigned long m;        uint8_t oldSREG = SREG, t; 1ce:     7f b7            in      r23, 0x3f        ; 63                cli(); 1d0:     f8 94            cli        m = timer0_overflow_count; 1d2:     80 91 02 01         lds     r24, 0x0102 1d6:     90 91 03 01         lds     r25, 0x0103 1da:     a0 91 04 01        lds     r26, 0x0104 1de:     b0 91 05 01        lds     r27, 0x0105#if defined(TCNT0)        t = TCNT0; 1e2:        66 b5            in      r22, 0x26        ; 38        #error TIMER 0 not defined#endif  #ifdef TIFR0        if ((TIFR0 & _BV(TOV0)) && (t < 255)) 1e4:        a8 9b            sbis    0x15, 0   ; 21 1e6:        05 c0            rjmp    .+10         ; 0x1f2 <delay+0x28> 1e8:        6f 3f             cpi     r22, 0xFF        ; 255 1ea:     19 f0            breq    .+6          ; 0x1f2 <delay+0x28>                m++; 1ec:     01 96             adiw    r24, 0x01        ; 1 1ee:     a1 1d            adc     r26, r1 1f0: b1 1d            adc     r27, r1#else        if ((TIFR & _BV(TOV0)) && (t < 255))                m++;#endif        SREG = oldSREG; 1f2: 7f bf            out     0x3f, r23        ; 63        return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());}void delay(unsigned long ms){        uint16_t start = (uint16_t)micros(); 1f4: ba 2f            mov     r27, r26 1f6: a9 2f            mov     r26, r25 1f8: 98 2f             mov     r25, r24 1fa:     88 27             eor     r24, r24 1fc:     86 0f             add     r24, r22 1fe:     91 1d             adc     r25, r1 200:        a1 1d            adc     r26, r1 202:        b1 1d            adc     r27, r1 204:        62 e0            ldi     r22, 0x02        ; 2 206:        88 0f             add     r24, r24 208:        99 1f             adc     r25, r25 20a:     aa 1f            adc     r26, r26 20c:     bb 1f            adc     r27, r27 20e:     6a 95             dec     r22 210:        d1 f7           brne    .-12         ; 0x206 <delay+0x3c> 212:        bc 01            movw    r22, r24 214:        2d c0            rjmp    .+90         ; 0x270 <delay+0xa6>        return m;}unsigned long micros() {        unsigned long m;        uint8_t oldSREG = SREG, t; 216:        ff b7           in      r31, 0x3f        ; 63                cli(); 218:        f8 94            cli        m = timer0_overflow_count; 21a:     80 91 02 01         lds     r24, 0x0102 21e:     90 91 03 01         lds     r25, 0x0103 222:        a0 91 04 01        lds     r26, 0x0104 226:        b0 91 05 01        lds     r27, 0x0105#if defined(TCNT0)        t = TCNT0; 22a:     e6 b5           in      r30, 0x26        ; 38        #error TIMER 0 not defined#endif  #ifdef TIFR0        if ((TIFR0 & _BV(TOV0)) && (t < 255)) 22c:     a8 9b            sbis    0x15, 0   ; 21 22e:     05 c0            rjmp    .+10         ; 0x23a <delay+0x70> 230:        ef 3f            cpi     r30, 0xFF        ; 255 232:        19 f0            breq    .+6          ; 0x23a <delay+0x70>                m++; 234:        01 96             adiw    r24, 0x01        ; 1 236:        a1 1d            adc     r26, r1 238:        b1 1d            adc     r27, r1#else        if ((TIFR & _BV(TOV0)) && (t < 255))                m++;#endif        SREG = oldSREG; 23a:     ff bf           out     0x3f, r31        ; 63void delay(unsigned long ms){        uint16_t start = (uint16_t)micros();        while (ms > 0) {                if (((uint16_t)micros() - start) >= 1000) { 23c:     ba 2f            mov     r27, r26 23e:     a9 2f            mov     r26, r25 240:        98 2f             mov     r25, r24 242:        88 27             eor     r24, r24 244:        8e 0f             add     r24, r30 246:        91 1d             adc     r25, r1 248:        a1 1d            adc     r26, r1 24a:     b1 1d            adc     r27, r1 24c:     e2 e0           ldi     r30, 0x02        ; 2 24e:     88 0f             add     r24, r24 250:        99 1f             adc     r25, r25 252:        aa 1f            adc     r26, r26 254:        bb 1f            adc     r27, r27 256:        ea 95            dec     r30 258:        d1 f7           brne    .-12         ; 0x24e <delay+0x84> 25a:     86 1b             sub     r24, r22 25c:     97 0b             sbc     r25, r23 25e:     88 5e             subi    r24, 0xE8        ; 232 260:        93 40             sbci    r25, 0x03        ; 3 262:        c8 f2           brcs    .-78         ; 0x216 <delay+0x4c>                        ms--; 264:        21 50             subi    r18, 0x01        ; 1 266:        30 40             sbci    r19, 0x00        ; 0 268:        40 40             sbci    r20, 0x00        ; 0 26a:     50 40             sbci    r21, 0x00        ; 0                        start += 1000; 26c:     68 51             subi    r22, 0x18        ; 24 26e:     7c 4f             sbci    r23, 0xFC        ; 252void delay(unsigned long ms){        uint16_t start = (uint16_t)micros();        while (ms > 0) { 270:        21 15             cp      r18, r1 272:        31 05             cpc     r19, r1 274:        41 05             cpc     r20, r1 276:        51 05             cpc     r21, r1 278:        71 f6            brne    .-100        ; 0x216 <delay+0x4c>                if (((uint16_t)micros() - start) >= 1000) {                        ms--;                        start += 1000;                }        }} 27a:     08 95             ret0000027c <init>:void init(){        // this needs to be called before setup() or some functions won't        // work there        sei(); 27c:     78 94             sei                // on the ATmega168, timer 0 is also used for fast hardware pwm        // (using phase-correct PWM would mean that timer 0 overflowed half as often        // resulting in different millis() behavior on the ATmega8 and ATmega168)#if defined(TCCR0A) && defined(WGM01)        sbi(TCCR0A, WGM01); 27e:     84 b5            in      r24, 0x24        ; 36 280:        82 60             ori     r24, 0x02        ; 2 282:        84 bd            out     0x24, r24        ; 36        sbi(TCCR0A, WGM00); 284:        84 b5            in      r24, 0x24        ; 36 286:        81 60             ori     r24, 0x01        ; 1 288:        84 bd            out     0x24, r24        ; 36        // this combination is for the standard atmega8        sbi(TCCR0, CS01);        sbi(TCCR0, CS00);#elif defined(TCCR0B) && defined(CS01) && defined(CS00)        // this combination is for the standard 168/328/1280/2560        sbi(TCCR0B, CS01); 28a:     85 b5            in      r24, 0x25        ; 37 28c:     82 60             ori     r24, 0x02        ; 2 28e:     85 bd            out     0x25, r24        ; 37        sbi(TCCR0B, CS00); 290:        85 b5            in      r24, 0x25        ; 37 292:        81 60             ori     r24, 0x01        ; 1 294:        85 bd            out     0x25, r24        ; 37        // enable timer 0 overflow interrupt#if defined(TIMSK) && defined(TOIE0)        sbi(TIMSK, TOIE0);#elif defined(TIMSK0) && defined(TOIE0)        sbi(TIMSK0, TOIE0); 296:        ee e6           ldi     r30, 0x6E        ; 110 298:        f0 e0           ldi     r31, 0x00        ; 0 29a:     80 81             ld      r24, Z 29c:     81 60             ori     r24, 0x01        ; 1 29e:     80 83             st      Z, r24        // this is better for motors as it ensures an even waveform        // note, however, that fast pwm mode can achieve a frequency of up        // 8 MHz (with a 16 MHz clock) at 50% duty cycle#if defined(TCCR1B) && defined(CS11) && defined(CS10)        TCCR1B = 0; 2a0:     e1 e8           ldi     r30, 0x81        ; 129 2a2:     f0 e0           ldi     r31, 0x00        ; 0 2a4:     10 82             st      Z, r1        // set timer 1 prescale factor to 64        sbi(TCCR1B, CS11); 2a6:     80 81             ld      r24, Z 2a8:     82 60             ori     r24, 0x02        ; 2 2aa:     80 83             st      Z, r24#if F_CPU >= 8000000L        sbi(TCCR1B, CS10); 2ac:     80 81             ld      r24, Z 2ae:     81 60             ori     r24, 0x01        ; 1 2b0:     80 83             st      Z, r24        sbi(TCCR1, CS10);#endif#endif        // put timer 1 in 8-bit phase correct pwm mode#if defined(TCCR1A) && defined(WGM10)        sbi(TCCR1A, WGM10); 2b2:     e0 e8           ldi     r30, 0x80        ; 128 2b4:     f0 e0           ldi     r31, 0x00        ; 0 2b6:     80 81             ld      r24, Z 2b8:     81 60             ori     r24, 0x01        ; 1 2ba:     80 83             st      Z, r24        // set timer 2 prescale factor to 64#if defined(TCCR2) && defined(CS22)        sbi(TCCR2, CS22);#elif defined(TCCR2B) && defined(CS22)        sbi(TCCR2B, CS22); 2bc:     e1 eb           ldi     r30, 0xB1        ; 177 2be:     f0 e0           ldi     r31, 0x00        ; 0 2c0:     80 81             ld      r24, Z 2c2:     84 60             ori     r24, 0x04        ; 4 2c4:     80 83             st      Z, r24        // configure timer 2 for phase correct pwm (8-bit)#if defined(TCCR2) && defined(WGM20)        sbi(TCCR2, WGM20);#elif defined(TCCR2A) && defined(WGM20)        sbi(TCCR2A, WGM20); 2c6:     e0 eb           ldi     r30, 0xB0        ; 176 2c8:     f0 e0           ldi     r31, 0x00        ; 0 2ca:     80 81             ld      r24, Z 2cc:     81 60             ori     r24, 0x01        ; 1 2ce:     80 83             st      Z, r24#if defined(ADCSRA)        // set a2d prescale factor to 128        // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.        // XXX: this will not work properly for other clock speeds, and        // this code should use F_CPU to determine the prescale factor.        sbi(ADCSRA, ADPS2); 2d0:     ea e7           ldi     r30, 0x7A        ; 122 2d2:     f0 e0           ldi     r31, 0x00        ; 0 2d4:     80 81             ld      r24, Z 2d6:     84 60             ori     r24, 0x04        ; 4 2d8:     80 83             st      Z, r24        sbi(ADCSRA, ADPS1); 2da:     80 81             ld      r24, Z 2dc:     82 60             ori     r24, 0x02        ; 2 2de:     80 83             st      Z, r24        sbi(ADCSRA, ADPS0); 2e0:        80 81             ld      r24, Z 2e2:        81 60             ori     r24, 0x01        ; 1 2e4:        80 83             st      Z, r24        // enable a2d conversions        sbi(ADCSRA, ADEN); 2e6:        80 81             ld      r24, Z 2e8:        80 68             ori     r24, 0x80        ; 128 2ea:     80 83             st      Z, r24        // here so they can be used as normal digital i/o; they will be        // reconnected in Serial.begin()#if defined(UCSRB)        UCSRB = 0;#elif defined(UCSR0B)        UCSR0B = 0; 2ec:     10 92 c1 00        sts     0x00C1, r1#endif} 2f0: 08 95             ret000002f2 <pinMode>:#define ARDUINO_MAIN#include "wiring_private.h"#include "pins_arduino.h"void pinMode(uint8_t pin, uint8_t mode){ 2f2: cf 93            push    r28 2f4: df 93            push    r29        uint8_t bit = digitalPinToBitMask(pin); 2f6: 48 2f             mov     r20, r24 2f8: 50 e0            ldi     r21, 0x00        ; 0 2fa:     ca 01            movw    r24, r20 2fc:     86 56             subi    r24, 0x66        ; 102 2fe:     9f 4f             sbci    r25, 0xFF        ; 255 300:        fc 01            movw    r30, r24 302:        34 91             lpm     r19, Z+        uint8_t port = digitalPinToPort(pin); 304:        4a 57             subi    r20, 0x7A        ; 122 306:        5f 4f             sbci    r21, 0xFF        ; 255 308:        fa 01            movw    r30, r20 30a:     84 91             lpm     r24, Z+        volatile uint8_t *reg, *out;        if (port == NOT_A_PIN) return; 30c:     88 23             and      r24, r24 30e:     69 f1            breq    .+90         ; 0x36a <pinMode+0x78>        // JWS: can I let the optimizer do this?        reg = portModeRegister(port); 310:        90 e0            ldi     r25, 0x00        ; 0 312:        88 0f             add     r24, r24 314:        99 1f             adc     r25, r25 316:        fc 01            movw    r30, r24 318:        e8 59            subi    r30, 0x98        ; 152 31a:     ff 4f            sbci    r31, 0xFF        ; 255 31c:     a5 91            lpm     r26, Z+ 31e:     b4 91            lpm     r27, Z+        out = portOutputRegister(port); 320:        fc 01            movw    r30, r24 322:        ee 58            subi    r30, 0x8E        ; 142 324:        ff 4f            sbci    r31, 0xFF        ; 255 326:        c5 91            lpm     r28, Z+ 328:        d4 91            lpm     r29, Z+        if (mode == INPUT) {  32a:     66 23             and      r22, r22 32c:     51 f4            brne    .+20         ; 0x342 <pinMode+0x50>                uint8_t oldSREG = SREG; 32e:     2f b7            in      r18, 0x3f        ; 63                cli(); 330:        f8 94            cli                *reg &= ~bit; 332:        8c 91             ld      r24, X 334:        93 2f             mov     r25, r19 336:        90 95             com     r25 338:        89 23             and      r24, r25 33a:     8c 93             st      X, r24                *out &= ~bit; 33c:     88 81             ld      r24, Y 33e:     89 23             and      r24, r25 340:        0b c0            rjmp    .+22         ; 0x358 <pinMode+0x66>                SREG = oldSREG;        } else if (mode == INPUT_PULLUP) { 342:        62 30             cpi     r22, 0x02        ; 2 344:        61 f4            brne    .+24         ; 0x35e <pinMode+0x6c>                uint8_t oldSREG = SREG; 346:        2f b7            in      r18, 0x3f        ; 63                cli(); 348:        f8 94            cli                *reg &= ~bit; 34a:     8c 91             ld      r24, X 34c:     93 2f             mov     r25, r19 34e:     90 95             com     r25 350:        89 23             and      r24, r25 352:        8c 93             st      X, r24                *out |= bit; 354:        88 81             ld      r24, Y 356:        83 2b             or       r24, r19 358:        88 83             st      Y, r24                SREG = oldSREG; 35a:     2f bf            out     0x3f, r18        ; 63 35c:     06 c0            rjmp    .+12         ; 0x36a <pinMode+0x78>        } else {                uint8_t oldSREG = SREG; 35e:     9f b7            in      r25, 0x3f        ; 63                cli(); 360:        f8 94            cli                *reg |= bit; 362:        8c 91             ld      r24, X 364:        83 2b             or       r24, r19 366:        8c 93             st      X, r24                SREG = oldSREG; 368:        9f bf            out     0x3f, r25        ; 63        }} 36a:     df 91            pop     r29 36c:     cf 91            pop     r28 36e:     08 95             ret00000370 <digitalWrite>:        }}void digitalWrite(uint8_t pin, uint8_t val){        uint8_t timer = digitalPinToTimer(pin); 370:        48 2f             mov     r20, r24 372:        50 e0            ldi     r21, 0x00        ; 0 374:        ca 01            movw    r24, r20 376:        82 55             subi    r24, 0x52        ; 82 378:        9f 4f             sbci    r25, 0xFF        ; 255 37a:     fc 01            movw    r30, r24 37c:     24 91             lpm     r18, Z+        uint8_t bit = digitalPinToBitMask(pin); 37e:     ca 01            movw    r24, r20 380:        86 56             subi    r24, 0x66        ; 102 382:        9f 4f             sbci    r25, 0xFF        ; 255 384:        fc 01            movw    r30, r24 386:        94 91             lpm     r25, Z+        uint8_t port = digitalPinToPort(pin); 388:        4a 57             subi    r20, 0x7A        ; 122 38a:     5f 4f             sbci    r21, 0xFF        ; 255 38c:     fa 01            movw    r30, r20 38e:     34 91             lpm     r19, Z+        volatile uint8_t *out;        if (port == NOT_A_PIN) return; 390:        33 23             and      r19, r19 392:        09 f4            brne    .+2          ; 0x396 <digitalWrite+0x26> 394:        40 c0            rjmp    .+128        ; 0x416 <digitalWrite+0xa6>        // If the pin that support PWM output, we need to turn it off        // before doing a digital write.        if (timer != NOT_ON_TIMER) turnOffPWM(timer); 396:        22 23             and      r18, r18 398:        51 f1            breq    .+84         ; 0x3ee <digitalWrite+0x7e>////static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));//static inline void turnOffPWM(uint8_t timer)static void turnOffPWM(uint8_t timer){        switch (timer) 39a:     23 30             cpi     r18, 0x03        ; 3 39c:     71 f0            breq    .+28         ; 0x3ba <digitalWrite+0x4a> 39e:     24 30             cpi     r18, 0x04        ; 4 3a0:     28 f4            brcc    .+10         ; 0x3ac <digitalWrite+0x3c> 3a2:     21 30             cpi     r18, 0x01        ; 1 3a4:     a1 f0           breq    .+40         ; 0x3ce <digitalWrite+0x5e> 3a6:     22 30             cpi     r18, 0x02        ; 2 3a8:     11 f5            brne    .+68         ; 0x3ee <digitalWrite+0x7e> 3aa:     14 c0            rjmp    .+40         ; 0x3d4 <digitalWrite+0x64> 3ac:     26 30             cpi     r18, 0x06        ; 6 3ae:     b1 f0           breq    .+44         ; 0x3dc <digitalWrite+0x6c> 3b0:     27 30             cpi     r18, 0x07        ; 7 3b2:     c1 f0           breq    .+48         ; 0x3e4 <digitalWrite+0x74> 3b4:     24 30             cpi     r18, 0x04        ; 4 3b6:     d9 f4           brne    .+54         ; 0x3ee <digitalWrite+0x7e> 3b8:     04 c0            rjmp    .+8          ; 0x3c2 <digitalWrite+0x52>        {                #if defined(TCCR1A) && defined(COM1A1)                case TIMER1A:   cbi(TCCR1A, COM1A1);    break; 3ba:     80 91 80 00         lds     r24, 0x0080 3be:     8f 77             andi    r24, 0x7F        ; 127 3c0:     03 c0            rjmp    .+6          ; 0x3c8 <digitalWrite+0x58>                #endif                #if defined(TCCR1A) && defined(COM1B1)                case TIMER1B:   cbi(TCCR1A, COM1B1);    break; 3c2:     80 91 80 00         lds     r24, 0x0080 3c6:     8f 7d             andi    r24, 0xDF        ; 223 3c8:     80 93 80 00         sts     0x0080, r24 3cc:     10 c0            rjmp    .+32         ; 0x3ee <digitalWrite+0x7e>                #if defined(TCCR2) && defined(COM21)                case  TIMER2:   cbi(TCCR2, COM21);      break;                #endif                                #if defined(TCCR0A) && defined(COM0A1)                case  TIMER0A:  cbi(TCCR0A, COM0A1);    break; 3ce:     84 b5            in      r24, 0x24        ; 36 3d0:     8f 77             andi    r24, 0x7F        ; 127 3d2:     02 c0            rjmp    .+4          ; 0x3d8 <digitalWrite+0x68>                #endif                                #if defined(TIMER0B) && defined(COM0B1)                case  TIMER0B:  cbi(TCCR0A, COM0B1);    break; 3d4:     84 b5            in      r24, 0x24        ; 36 3d6:     8f 7d             andi    r24, 0xDF        ; 223 3d8:     84 bd            out     0x24, r24        ; 36 3da:     09 c0            rjmp    .+18         ; 0x3ee <digitalWrite+0x7e>                #endif                #if defined(TCCR2A) && defined(COM2A1)                case  TIMER2A:  cbi(TCCR2A, COM2A1);    break; 3dc:     80 91 b0 00        lds     r24, 0x00B0 3e0:        8f 77             andi    r24, 0x7F        ; 127 3e2:        03 c0            rjmp    .+6          ; 0x3ea <digitalWrite+0x7a>                #endif                #if defined(TCCR2A) && defined(COM2B1)                case  TIMER2B:  cbi(TCCR2A, COM2B1);    break; 3e4:        80 91 b0 00        lds     r24, 0x00B0 3e8:        8f 7d             andi    r24, 0xDF        ; 223 3ea:     80 93 b0 00        sts     0x00B0, r24        // If the pin that support PWM output, we need to turn it off        // before doing a digital write.        if (timer != NOT_ON_TIMER) turnOffPWM(timer);        out = portOutputRegister(port); 3ee:     e3 2f            mov     r30, r19 3f0: f0 e0           ldi     r31, 0x00        ; 0 3f2: ee 0f            add     r30, r30 3f4: ff 1f            adc     r31, r31 3f6: ee 58            subi    r30, 0x8E        ; 142 3f8: ff 4f            sbci    r31, 0xFF        ; 255 3fa:     a5 91            lpm     r26, Z+ 3fc:     b4 91            lpm     r27, Z+        uint8_t oldSREG = SREG; 3fe:     2f b7            in      r18, 0x3f        ; 63        cli(); 400:        f8 94            cli        if (val == LOW) { 402:        66 23             and      r22, r22 404:        21 f4            brne    .+8          ; 0x40e <digitalWrite+0x9e>                *out &= ~bit; 406:        8c 91             ld      r24, X 408:        90 95             com     r25 40a:     89 23             and      r24, r25 40c:     02 c0            rjmp    .+4          ; 0x412 <digitalWrite+0xa2>        } else {                *out |= bit; 40e:     8c 91             ld      r24, X 410:        89 2b             or       r24, r25 412:        8c 93             st      X, r24        }        SREG = oldSREG; 414:        2f bf            out     0x3f, r18        ; 63 416:        08 95             ret00000418 <main>:#include <Arduino.h>int main(void) 418:        cf 93            push    r28 41a:     df 93            push    r29{        init(); 41c:     0e 94 3e 01         call    0x27c    ; 0x27c <init>#if defined(USBCON)        USBDevice.attach();#endif                setup(); 420:        0e 94 97 00         call    0x12e    ; 0x12e <setup>            for (;;) {                loop();                if (serialEventRun) serialEventRun(); 424:        c0 e0           ldi     r28, 0x00        ; 0 426:        d0 e0           ldi     r29, 0x00        ; 0#endif                setup();            for (;;) {                loop(); 428:        0e 94 80 00         call    0x100    ; 0x100 <loop>                if (serialEventRun) serialEventRun(); 42c:     20 97             sbiw    r28, 0x00        ; 0 42e:     e1 f3           breq    .-8          ; 0x428 <main+0x10> 430:        0e 94 00 00         call    0        ; 0x0 <__vectors> 434:        f9 cf           rjmp    .-14         ; 0x428 <main+0x10>00000436 <_exit>: 436:        f8 94            cli00000438 <__stop_program>: 438:        ff cf           rjmp    .-2          ; 0x438 <__stop_program
<![CDATA[LuxBlaster: Frequently Asked Questions]]>Sat, 08 Mar 2014 12:17:51 GMThttp://www.techbitar.com/blog/luxblaster-frequently-asked-questionsDRAFT

With my LuxBlaster project leaving the comfortable realm of DIY online media and leaking into mainstream online media, and with the demo video going viral, it opened up the door for all sorts of misunderstandings, paranoid suspicions, and threatening arguments that touch on the freedom and legality of making technical prototypes for learning and experimentation. 

It turns out DIY projects that may seem benign to fellow tech makers can still make others uncomfortable and suspicious. Even though the majority of media coverage of the LuxBlaster was neutral or positive as well as the video ratings, yet the intensity of the negative interactions on YouTube and some of the emails I received was unusual and reflected strong feelings of fear and loathing pertaining to slow drivers and to the legality/ethics of experimental prototyping.  

Electronics makers and prototypers tend to underestimate the power of creating things because we do it all the time. But to some in the non-technical mainstream world there is no such thing as an experimental prototype built just for learning or fun. The intense exchanges on the LuxBlaster YouTube comments section are a case in point. 

I welcome discussion on my LuxBlaster but after a while the comments and questions start to repeat and fall into the same pattern. I know some commentators simply are looking for a venue to air their frustrations regardless of the facts. I am glad the LuxBlaster can give them this satisfaction. Better to scream at a geek and his prototype than to take it out on other drivers on the road. For the rest, here's a list of Frequently Asked Questions along with my answers. 


The LuxBlaster 3W LED puts out 230 Lumens. This is annoying at best but no match for the disorienting power of a 3000 Lumens xenon auto headlamp. For two auto headlamps, that's 6000 blinding Lumens coming from behind your car. 


Welcome to the Makers Movement. It's part of the Do-it-Yourself  (DIY) culture.  We are individuals (not businesses) who like to make things be it electronic, mechanical, etc for experimentation. This culture is driven by learning through prototyping. A prototype is a proof of concept but not a completed product.  The end result most of the time is a project that we share with other like-minded  makers to solicit feedback and maybe open new creative possibilities to other makers through a process known as re-use thanks to open source licenses. There's often no material benefit but plenty of self-satisfaction. A maker is an artist who expresses him/her self through electro-mechanical creations. If you Google the term "Makers Movement" or DIY you will come across a long list of persons and groups interested in making things.  The heart of the modern makers movement (about 10-years old) is  an enabling technology  known as the Arduino (http://arduino.cc). It's simple to learn, backed by a vast ecosystem of non-profit support, education, and after market tools. This is the context through which the LuxBlaster was made. The fact the mainstream online media was interested in it does not turn the LuxBlaster into a commercially viable product or change its nature as a modest experiment built over a weekend for a tech club workshop


On a scale from 1 to 10 with 10 being most dangerous prototype, the LuxBlaster is a 1. First, it's not a product that you can buy. But you can buy a gun or a rifle today. Second, the LED light on the LuxBlaster emits 230 Lumens which is hardly dangerous. Yet the 6000 Lumens from two xenon headlamps beaming at you from a speeding road bully behind your car or driving from the other direction is more dangerous. Third, the LuxBlaster can only be built by technical people, so it's not a mass market product. Four, if someone wants to get back at a road bully, they don't need a LuxBlaster, they use their brakes. Now, is this wrong and dangerous.


I did not share the LuxBlaster with the world. I only sent the project link to two of my favorite makers portals.  It seems other trade journals picked up my project from those portals. Next thing the LuxBlaster was leaking into mainstream online media. I have no problem with that except that some angry motorist who are looking to air their frustrations turned the LuxBlaster into a piñata and proceeded to hammer at it ignoring in the process my disclaimers and the context (educational prototype) through which it was made (tech club experimentation). On the positive side, the viral LuxBlaster video generated a healthy but intense discussion on road safety. 


I am not a slow driver. If any, I am an impatient driver. And if someone is flashing me to switch lanes, I respond quickly. Heck, I am not even an ideal driver.  I did not design the LuxBlaster to make a statement or champion a cause. The LuxBlaster was designed as a demo for a workshop in my tech club called Pin13 Protospace. But angry motorists insisted on turning the LuxBlaster into a lightning rod. That's fine with me but when some commentators on both sides of the argument posted violent threats I realized the depth of their anger. 


I make things to explore, experiment, and to share. I have built dozens of gadgets over the years. Gadgets that I liked either because of their educational value or originality I document and publish on my website (http://techbitar.com) and shared on portals for electronics makers. There are hundreds of makers who share my passion for making things. We don't make good or bad things. We make things for our own edification. One of my projects is a PEZ Robo Dispenser. Is this a good or bad prototype? Some will say it's a useless invention while others will consider it interesting. I knew when I built the Pez Robo Dispenser that it's a one-shot deal to be used in one of my workshops knowing that students will find it amusing. That is that. When I am done with one of my projects, I disassemble and reuse the same parts for the next project. It's like a grown-up Lego. 


Legal or not, no one should take the LuxBlaster on the road or use it in a real world situation. The LuxBlaster is a lab experiment.


I think so, if automakers and policymakers work together. I have written a blog entry on the role of technology in improving car-2-car and driver-2-driver communications to improve road safety. 
<![CDATA[Car-2-Car Communications: When Will Automakers Catch Up With Technology]]>Tue, 04 Mar 2014 07:40:07 GMThttp://www.techbitar.com/blog/beyond-luxury-the-state-of-car-to-car-networking-communications(DRAFT)

Recently I built the LuxBlaster, a robot that monitors and tracks intense light sources coming from behind a car. When the intensity of the light source increases beyond a predetermined threshold (e.g. blinding light), the LuxBlaster will blast a warning light to the driver behind to lower his/hear high beam in the same manner we flash incoming car drivers who blast their high beams.  

The LuxBlaster prototype was my scifi response to road bullies who use their headlight as a weapon to intimidate other drivers instead of their intended purpose of improving visibility at night. The LuxBlaster was a lab-only robot for workshop demo purposes but it generated unexpected reactions. 

To my surprise, the LuxBlaster video went viral reaching 200,000 viewers in 5 days. Angry motorists exchanged barbed comments online. So many drivers suffered the abuse of road bullies who use their high beam to disorient and to intimidate. But on the other hand there were legitimate complaints of inconsiderate motorists who drive leisurely ignoring the traffic jam behind them.  

And while the LuxBlaster was never intended to be a real product to be installed in automobiles, drivers on both sides of the high beam divide greeted the LuxBlaster as if it were a real product that can make an impact. Some welcomed the LuxBlaster as a savior but others were intensely hostile, despite my repeated mentions that this is not a product to be used on the road. 

It then hit me. We are so dependent on technology to solve our problems yet in the case of automakers, we have been let down by their failure to use mainstream communications technology to improve road safety. 

The technology exists to improve driver-driver and car-car communications yet lack of adoption by automakers leaves motorists stuck using primitive modes of communications such as flashing high beams and honking. 

Cars have advanced technologically on many fronts mainly luxury and fuel efficiency, yet the means by which drivers and cars communicate and network on the road to improve driving safety remain mysteriously primitive. 

Outside the car, we have an array of technologies to aid in person to person communications such as video, Bluetooth, Wi-Fi  GSM and more yet the moment we step inside the car and start to move, we are only permitted to honk, wink, or blink. 

As an IT person I know the importance of backward compatibility. But what automakers are pursuing in on the road communications is pure backwardness. 

Today, a car is a fortified moving metal container and only sign language is permitted with the outside world. Not much has changed in this regard since the Benz "Velo" was made in 1894. 

We have so many proposed automobile innovations to aid on the road communications between drivers and cars yet very little of this technology has made it to mainstream cars.  

The Frankfurt Motor Show of 2013 showcased a number of car innovations, mostly expensive and geared at luxury. Very few practical innovations were introduced in terms of networking and communications between drivers. 

This is where visionary policymakers as well as consumer safety groups must step in and propose/require technological milestones for automakers to enhance car-car and driver-driver networking and communications to reduce accidents and increase road safety.  

Here's a simple auto innovation: the auto black box that constantly registers a car's vitals and logs inertial data to be retrieved and analyzed in case of an accident or legal situation.  In case of a hit/run, for example, the black box can capture the wirelessly transmitted ID of the offending car which also has a black box with time stamp data revealing its exact location and inertial data such as speed and acceleration at a given time. 

What about smart headlights that lower their beam the closer they are to another car. Proximity sensors that provide feedback while driving to warn of dangerously close objects such as nearby cars or pedestrians. Video cameras that monitor a car's blind spots. Many of these technologies exist but they are not mandatory. 

The drop in price of quality sensors and portable AV systems calls for a cost/benefit analysis to determine the viability and benefit of requiring automakers to include these technologies in all passenger cars.

Privacy concerns must be addressed but these technologies won't be more intrusive on privacy than the average smart phone or PC. Except that we have the added benefit of saving lives and reducing insurance premiums. 

Even if automakers are not interested in technology-based road safety, smartphone developers can capitalize on the sophistication of inertial and location sensors built into newer smart phones as well as the built-in phone communications protocols to aid in on the road networking with other drivers to increase safety. 

Automakers have no incentive to take the leap into car-car networking or driver-driver communications technologies because of the cost of R&D.  But when government makes this technology policy, it becomes a level-playing field for all automakers. ]]>
<![CDATA[Can Android/Arduino Combo Accelerate The Global Electronics DIY Revolution? ]]>Mon, 11 Nov 2013 11:17:35 GMThttp://www.techbitar.com/blog/can-androidarduino-combo-accelerate-the-global-electronics-diy-revolution
Many geeks will eventually outgrow the capabilities of the 8-bit platform and turn to complementary technologies to bolster their projects with more computing power.  For those who already have an Android device, search no more. 

By Hazim Bitar (techbitar.com)

For Arduino prototypers who needed additional computing power, be it for image processing or other CPU-intensive applications, Windows/Intel computers made a logical first choice simply because of their availability and ease of interface to Arduino using solutions such as FTDI's USB to RS232. But the cost, bulkiness of Windows/Intel platform and the closed source OS left an open niche to be filled with compact and inexpensive alternatives.  Enter the Raspberry Pi.

The affordable and diminutive SoC-based Raspberry Pi ($40) has become a popular choice for prototypers since its introduction a couple of years ago. With more SoC (System on a Chip) solutions in the pipeline such as the Arduino TRE and Galileo, it's reasonable to ask this question:  if you already own an Android device with a powerful ARM processor, GPU, sensors, and multimedia features why not leverage it for prototyping and hacking?

If you are an obsessive compulsive electronics prototyper like me you will soon discover that adding additional electronic components and functionality to Arduino or Raspberry Pi will obviate the initial low-cost of ownership. In my case, it adds up to over $400 in component purchases. (See attached table). Most of those components already exist in the majority of mid-range Android smartphones and tablets that are already in wide global circulation. 

Built-in components such as WiFi, Bluetooth, GPS, SD, touch screen, accelerometer sensor, speaker, mic, camera, and much more can transform the Android device into a powerful compact computing platform to pair with the Arduino Uno on par with the Raspberry Pi, BeagleBone, and the next generation of Arduino/ARM compact computing SoC platforms.  

Inversely, Arduino can extend the sensory capabilities of Android devices by adding sensors that are not typically built-into with Android such as gas, radiation, PIR, pulse, etc. 

The Android OS is open source like Linux and also benefits from a vast support and education ecosystem. 

File Size: 204 kb
File Type: pdf
Download File


As for market share, Android can be found everywhere. According to a senior vice president at Google, more than 1 billion Android devices have been activated as of mid 2013.  That's 1 billion potential prototyping and hacking platforms already operational. And according to the Gartner Group, Android is expected to retain 50% of the mobile OS market well into 2016. 

Android devices are growing in power and sophistication as they slide down the price/function curve. But very few geeks think of their Android smartphone as a powerhouse of hacking and electronic experimentation.  

In many countries, shipping costs and custom tariffs will add significant costs to your prototype.  In countries with paranoid and corrupt regimes, you may end up paying 100% or more of the value of imported items often in contradiction with the published low custom tariffs which are advertised to lure investors.  I speak from personal experience. 

Not to mention the absurd security procedures you will be subjected to in those countries when dealing with imported components such as barebone GPS and GSM modules. Having those electronic items already built into your Android smartphone, which are imported and traded with ease as mainstream consumer products, saves money and headaches.  


Having a proven open source OS such as Linux as a software platform has also been a strong selling point for the Raspberry Pi. The Android OS offers a similar advantage being open source with tight hardware integration and a rich set of APIs to tap into built-in electronic components.

The skills required to program an Android device are no more challenging than programming Linux. Yet the tight integration between the Android APIs and the built-in hardware components such as sensors and communications sub-modules translate to more time making and less time on low level hacking. 


In the realm of barebone electronics, components communicate mostly via pins and intra-circuit communications protocols such as I2C, SPI, and UART. But in the realm of Android, you will be hard pressed to find GPIO pins protruding from your Android phone ready to be connected with jumper wires to another circuit. Android phones will typically have a USB port and an audio jack. 

Google offers the Accessory Development Kit (ADK) that can facilitate the interface between Android devices and Arduino. This has proven a costly solution with limited acceptance and support. The ADK requires the Android device to support certain hardware features such as USB Host that are found in expensive top of the line Android devices. 

Prototypers soon found a way to painlessly interface Android devices with the Arduino using inexpensive serial Bluetooth communication modules.

Using a $10 HC-05 Serial Bluetooth module (which can be purchased from ebay.com) attached to an Arduino Uno you can start sending and receiving data generated by the Android's built-in components and apps to Arduino or any microcontroller or computer equipped with serial Bluetooth. It's possible to send/receive data from Android devices using WiFi and USB too but currently Bluetooth is far cheaper. 

Already, developers published guides and uploaded various ready-to-run Android apps to interface Android with Arduino to aid prototypers with no Android programming skills. 

I have published two Android apps on Google Play to bridge between Android and Arduino. The first app is ArduDroid which allows you to wirelessly control Arduino Uno pins from your Android device. 

The other app is SensoDuino which harvests data in real-time from over a dozen Android sensors (the ones which exist on your phone model) and sends this data to your Arduino wirelessly. Android built-in sensors include GPS, Gyro, Accelerometer, Compass, Light, Audio, Temperature, etc. 

Amarino is another nice Android app that also harvests Android sensors. Then there is ArduinoCommander to control your Arduino board from your Android device over Bluetooth, Ethernet or USB. If you search for Arduino on Google Play you will be presented with a number of apps that help Arduino interface with Android. 


An unintended but welcome benefit to using Bluetooth for Arduino-Android interfacing is the vanishing of spaghetti cabling which is the hallmark of electronics prototyping. Imagine wiring 5 components to your Arduino or Raspberry Pi such as Bluetooth, gyro, GPS, touch screen, and speaker. 

The cabling and shield stacking will add considerable bulk let alone the time it takes for debugging software integration between these components.  

The neatness factor of wireless Bluetooth communication adds to the attractiveness of the Arduino-Android combo.  Wireless is all the rage. Even phone battery charging is going wireless. 


For prototypers, there are times when wiring a project from basic components is desirable especially for the educational value. Other times, a feature-rich compact hardware platform with computing power and a well-supported open source OS is needed for the task at hand. 

If you already have an Android device and an Arduino Uno, together they can serve as a powerful DIY platform. So why not save money and recruit your Android for geeky pursuits.

With over a billion Androids world-wide, even 1% of Android users could make a significant contribution to the global electronics DIY movement. 
<![CDATA[Modular smartphone designs are cool but may produce more e-waste]]>Tue, 05 Nov 2013 12:14:50 GMThttp://www.techbitar.com/blog/modular-smartphones-designs-are-cool-but-may-produce-more-e-waste
Talented Dutch designer Dave Hakkens has come up with a brilliant design idea for smartphones. Why not design smartphones to be modular. Snap off the old or damaged parts and snap on the new better performing ones. 

His main selling points are ease of upgrades/repairs as well as reduction in hazardous wastes. While I agree with Hakkens on ease of upgrade and repairs, yet it's not clear how throwing away old smartphone components whenever better ones are introduced can reduce hazardous waste.  

The desktop PC was one of  those successful but unruly implementations of modular electronics for a consumer product. Hakkens's idea will bring compactness and form to modular smartphones and possibly other consumer electronics.

I like modular designs. The idea oozes neatness. Squarish things that fit neatly together bring back warm LEGO memories. Snap out the old and snap in the new and you can custom-build a new phone altogether. Sounds like a winner to me, but it is not a green idea. If any, modular phones may generate more hazardous trash as more and more phone users purchase upgrades on a regular basis and throw away the old parts. 

A complete functional phone, when discarded due to old age, for example, can still be recycled by other users. But what will happen to old discarded phone components such as an old GPS module or an old touchscreen? Will these components trickle down to other users with greater or less frequency than whole phones? Who knows.

I tend to keep my phones for about 3 years before I give them away. But let's assume for a moment that every 3 years or so my phones end at the top of the hazardous e-waste heap.

If I own a modular smartphone, I would most likely swap my old camera with a newer hi-res modular camera and throw away the old one. Weeks later, if a new GPS module comes along for my phone, my old GPS will get swapped out. My WiFi module too. Maybe when Bluetooth 5.0 comes out I will swap it with the old Bluetooth. 

And since not many countries handle hazardous electronic waste disposal properly, my old camera, GPS, WiFi, and Bluetooth modules will find their way into municipal trash dumps. How is this any better than traditional phone designs as far as being environment-friendly? Is generating e-trash year-round better on the environment then let's say generating trash every 2-3 years when a phone is discarded?

In reality, being the pack rat that I am, no electronic part will be discarded but instead will find a home in an Arduino geeky project. But you see the picture. Millions of phone users swapping and discarding old smartphone modules with newer better ones. This can generate e-waste too.  

So yes to modular smartphones because it's a neat and efficient idea but as long as we realize the cost to the environment is still unclear. 

Modular smartphones should not be promoted as environmentally-friendly alternatives to traditional smartphone designs.  They should be promoted as a smart, functional design.