Quantcast
Channel: Embedded Lab
Viewing all 713 articles
Browse latest View live

XMega ADC

$
0
0

For users of advance MCUs like the XMega it is not necessary to tell what an analog-to-digital converter (ADC) is or what it does. I assume this is not the first family of microcontroller they are dealing with. Unlike the ADCs of other microcontroller the ADC of XMega devices is a highly complex tool. The level of complexity is so much that without understanding every bits-and-pieces of this piece of hardware a user won’t enjoy its absolute power. XMega ADC is also the most confusing hardware as it is not like other MCU ADCs. We will be dealing with ATXMega32A4U and it has only one ADC block, named ADCA but some other XMega devices like the XMega128A1 have more than one ADC block – ADCA and ADCB. By the way the XMega reference manual provides a long literature on the ADC and I’m not willing to state everything.

A quick view of the ADC block diagram shows most of the internal arrangement.

ADC internal

To begin with, there are some prerequisites. The very first thing is to realize the inputs of the ADC block (VINP and VINN) as like the two inputs of a regular op-amp. The ADC is differential in nature. Secondly there are several areas that need more than a few lines of “ATMEL” explanation and several assumptions. We can’t see the internal circuitry after all. Take things initially as if they are in black boxes and then slowly but systematically probe them until fully unveiled. This is somewhat a my-kind of learning technique. Thirdly a word of caution, an ADC channel doesn’t necessarily mean a physical ADC pin as in traditional MCUs. In the XMega32A4U there’s one physical ADC - ADCA comprising of four virtual channels that can be connected to a number of signal sources both internal and external (physical pins). Lastly we won’t be using 8 bit ADC conversions in our discussion anywhere as it is less precise and seldom used. However 8 bit conversions are faster than 12 bit ones.


Key Pros and Cons of XMega ADCs


Pros:

  • Pipeline Architecture – Simply this feature allows one sample to be processed while another is being acquired.  Here’s a conceptual view of how this stuff works.

pipeline

  • ADC’s power consumption can be controlled.
  • High sampling rate (2Msps) and high resolution (12 bits).
  • Several options for reference source.
  • Conversion frequency can be set by pre-scaling peripheral clock.
  • Signed/unsigned modes.
  • Differential and single-end measurements.
  • Front-end gain stage for differential modes, allowing amplification of small signals.
  • ADC conversion can be triggered by events, timer interrupts, DMA requests and so on.

Cons:

  • Unlike ordinary MCUs like the traditional AVR ATMega MCUs, ADC reference can’t be more than (VDD – 0.6) volts even if the reference source is externally connected.
  • Calibration values are stored in signature row and these must be manually read and written to ADC. Again this feature is not common in the most popular microcontrollers.
  • In terms of volts per ADC count and general perception, the ADC is not really 12bit but rather somewhat 11 bits or some less than 12 bit. More explanations later.
  • In the unsigned single-ended mode of operation a small amount of positive offset is internally added to detect zero-cross. This is the reason why people will not get zero count at zero voltage. You will rather get a count of about 200 or so at zero voltage. This offset should be compensated in the software end and in the process the ADC is no long a 12 bit ADC for general purpose uses. Owing to this offset the maximum value of voltage the ADC can measure is also below the reference voltage. However a tiny amount of negative voltage can be detected in this mode.

ADC Characteristics

Differential Mode

People who have dealt with instrumentations or analog electronics will certainly know what a differential amplifier is. Well basically it just amplifies/passes the difference in signal between its two input terminals. Simply Vout = m x (VinpVinn), where m is the gain, Vinp is the positive input and Vinn is the negative input. In the XMega ADC block this differential mode is technically the same stuff. You have two ADC pins as inputs in differential mode and an optional gain stage. Typically use of  differential mode is that for measuring current flowing through a shunt. However a few things are to be strictly followed:

  • Only signed conversion is possible in differential mode. Thus the 12bit ADC count has a range from -2048 to 2047, centering at 0.
  • All pins can be positive inputs but only a few specified and be negative inputs. Only ADC0 – ADC3 pins can be negative input pins in differential mode without gain while only ADC4 – ADC7 pins can be negative input pins in differential mode with gain. Other than these pins, negative inputs can also be tied with either the internal or pad (external) ground. When the negative input is tied to ground and an ADC input is used, the result is a signed single-ended ADC.
  • Gain can be set according to need but the value of gain is a multiple of 2, ranging 0.5x to 64x.
  • Additional gain stage adds additional propagation delays.

 

differential without gain

 

 

differential with gain

 

Single-Ended Mode

This is what people use mostly. Unlike the differential mode it has both signed and unsigned conversion mode of operation. The only difference between these modes is to what the negative terminal of the ADC block is connected to. Apparently single-ended mode seems to be the easiest and simple mode of operation but trust me this mode is where people get their head blown off. It took several days for me to understand this mode completely. Before going on further please note all of the figures, tables and formulae are taken from Atmel’s official docs and so nothing is based on imagination.

The key region of confusion of unsigned single-ended conversion mode is the ∆V offset. Its physical value is about 5% of the reference and so if the reference is 1.0V then its value is 0.05V. Remember what I said about differential amp earlier? If so then check the block diagram shown below.

single_ended_unsigned

 

The negative input is connected to some sort of reference. This is the first piece of confusion and things get more complicated to realize when you go through the formula for unsigned single-ended ADC conversion, which is:

Formula 1

 

Note that the formula and the block diagram don’t technically agree with each other. Throughout all Atmel’s technical docs I found the same stuff over and over again with no elaborate explanation. However what I found during my research is that the formula is consistent. I didn’t find any answer to the missing VREF / 2 part. My first question was why it is connected to some sort of offset rather than zero. The answer is somewhat both easy and complicated. By having the ADC configured internally this way an XMega ADC pin connected to ground (0.0V) does not give 0 ADC count but about 200 ADC counts. I thought it was a hardware bug and that the ADC is not truly a 12 bits ADC but somewhat less than that. The more I researched the more I found it to be useful. If 0V in an ADC pin results about 200 counts then definitely a small negative voltage at that ADC pin will result 0 ADC count. According to Atmel this offset helps to detect zero-crossing or true 0V rather than something near to 0V like ±0.001. I found that the XMega ADC can, in fact, detect a tiny quantity of negative potential. Usually we don’t use this feature with common ADC uses but in certain precision instrumentations we need to know this and there this offset plays its part. If you check XMega datasheet then you’ll notice that ADC input voltage range spans from -0.1V to (AVCC + 0.1) V. Though this feature has its advantage in some certain areas it comes at a cost of reduced top range which about 95% of the reference source’s value. If, for example, the internal 1.0V reference is used then the ADC can measure voltages ranging from about -0.05V to about 0.95V. Thus it is still measuring a 1.0V span with 12 bits precision though apparently it may not look like that at first experience. Fortunately MikroC PRO for AVR compiler’s ADC library is based on this mode of operation and so be aware not to curse yourself.

In the signed single-ended mode VINN is connected to ground and it is quite a simple story. In the signed mode the result of an ADC conversion is always 11bits. The MSB is used for sign. However you cannot apply negative voltage to an ADC pin with respect to ground under any circumstances except what your device’s datasheet states. You’ll get 0 – 2047 counts for 0V – VREF range.

 

single_ended_signed

 

My Experiences and Findings

I found a number of stuffs that I feel needs to be shared apart from whatever I already stated. In my experience the internal 1.0V source is not good enough as a reference source for ADC because it needs a lot of caution and even some people claim that Atmel said that this source is technically too low for an ADC reference. I did try to use it but I found it to be too sensitive to noise. At this point Atmel recommended to shut down all operations of the MCU or go to sleep mode during capturing an ADC sample. This may not be always possible. There are other options for reference source but I found out that the best one is the VCC / 1.6 reference source. With 3.3V VCC, it is about 2.06V. However a lot of care is needed to ensure a good stable VCC. Since a MCU is a digital device there will be switching noise across the power lines and to reduce them we need to follow basic EMI and PCB routing principles. AVCC pins should be connected to VCC via a ferrite bead and a 100nF capacitor. All other VDD pins should have 100nF capacitors connected between them and ground. Another good solution for ADC reference source is to use external reference sources like TL431 and similar.

Since the ADC is of 12 bit resolution and the reference source is less than 3.3V, the ADC block will tend to pick up noises and tiny fluctuations. The ADC count may vary as much as 60 counts. To avoid these we need to follow recommendations from Atmel and apply some basic tips. ADC values should be averaged in the software end. If possible ADC pins should be buffered and filtered externally with proper low pass LC filter. XMega ADCs offer high impedance and low impedance modes along with other options to control ADC power consumption. Temperature compensation can also be used to improve ADC accuracy. If properly configured a lot of problem is dealt with easily.

 

A must do process is to get rid of any offset before using the ADC for actual measurements. This can be done in two ways. First is to ground any ADC pin that will be used for taking measurements later, get the ADC offset with that pin and then use it normally as it was intended. This offset is common and so it is not needed to measure the offset for all ADC pins. The other method is to dedicate an ADC pin to ground and it will never be disconnected from ground. This will measure the offset only. In terms of pin count this method is expensive but it is the most hassle-free process. Actually I prefer this method.

 

In most applications the signed single-ended mode is the best to use. The other is to use differential mode without gain and negative input tied to ground. When using differential mode with gain be aware of noise because noise also gets amplified along with signal. Be sure to select proper ADC sampling frequency. For general purpose uses something from 60 – 150kHz as sampling rate is good enough. Please also note that Atmel recommends that the user must access and load factory calibration bytes for  proper operation of the ADC. Frankly speaking in all of the XMega MCUs I have at my disposal, I found that the calibration bytes for ADC in them are 0×00. I don’t find it necessary to load these meaningless values but I still used them in my coding to go by Atmel’s recommended way.

 

Before using a ADC pin make sure that it is a floating pin. If you have read my previous post on XMega I/O ports then you must know how to do it.

 

Code Examples

Just as before, I added a header file for ADC along with the header files for clock and I/O ports. This will greatly reduce coding time and efforts. In my coding I followed a systematic procedure to configure the MCU. I recommend following this method. First configure the XMega clock, then I/O port pins and finally the ADC itself. In all of my example codes the XMega CPU is configured to run at 8MHz clock speed and only PORTA pins are used for ADC inputs. A LCD with the help of MikroC’s library provided a mean to see ADC data during tests.. As always using MikroC’s libraries are fun, fast and easy but they come at the cost of reduced customizations and relatively larger code sizes. Shown below is the basic setup:

 

Schematic

 

XMega ADC with MikroC’s Library

 

#include <io.h>
#include <clock.h>
 
 
sbit LCD_RS at PORTC_OUT.B2;
sbit LCD_EN at PORTC_OUT.B3;
sbit LCD_D4 at PORTC_OUT.B4;
sbit LCD_D5 at PORTC_OUT.B5;
sbit LCD_D6 at PORTC_OUT.B6;
sbit LCD_D7 at PORTC_OUT.B7;
 
sbit LCD_RS_Direction at PORTC_DIR.B2;
sbit LCD_EN_Direction at PORTC_DIR.B3;
sbit LCD_D4_Direction at PORTC_DIR.B4;
sbit LCD_D5_Direction at PORTC_DIR.B5;
sbit LCD_D6_Direction at PORTC_DIR.B6;
sbit LCD_D7_Direction at PORTC_DIR.B7;
 
 
void setup();
signed int adc_avg(unsigned char no_of_samples, unsigned char channel);
void lcd_print(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char cnt_volt);
float map(float v, float x_min, float x_max, float y_min, float y_max);
            
 
void main()
{
     signed int adc = 0;
     signed int offset = 0;
     float v = 0;
 
     setup();
     offset = adc_avg(100, 0);
     
     lcd_out(1, 1, "V:");
     lcd_out(2, 1, "ADC:");
     
     while(1)
     {
              adc = adc_avg(50, 1);
 
              v = map(adc, offset, 4095.0, 0, 1959.375);
              
              lcd_print(4, 1, v, 0);
              lcd_print(5, 2, adc, 1);
              delay_ms(600);
     };
}   
 
 
void setup()
{
     OSC_CTRL |= OSC_RC32KEN_bm;
     while(!(OSC_STATUS & OSC_RC32KRDY_bm));
     OSC_CTRL |= OSC_RC32MEN_bm;
     CPU_CCP = CCP_IOREG_gc;
     CLK_PSCTRL = ((CLK_PSCTRL & (~(CLK_PSADIV_gm | CLK_PSBCDIV1_bm | CLK_PSBCDIV0_bm)))
                  | CLK_PSADIV_1_gc | CLK_PSBCDIV_2_2_gc);
     OSC_DFLLCTRL = ((OSC_DFLLCTRL & (~(OSC_RC32MCREF_gm | OSC_RC2MCREF_bm))) |
                    OSC_RC32MCREF_RC32K_gc);
     
     DFLLRC32M_CTRL |= DFLL_ENABLE_bm;
     while(!(OSC_STATUS & OSC_RC32MRDY_bm));
     CPU_CCP = CCP_IOREG_gc;
     CLK_CTRL = ((CLK_CTRL & (~CLK_SCLKSEL_gm)) | CLK_SCLKSEL_RC32M_gc);
     OSC_CTRL &= (~(OSC_RC2MEN_bm | OSC_XOSCEN_bm | OSC_PLLEN_bm));
     PORTCFG_CLKEVOUT = 0x00;
     
     PORTD_OUT = 0x00;
     PORTD_DIR = 0x02;
     PORTD_PIN0CTRL = (PORT_OPC_BUSKEEPER_gc | PORT_ISC_BOTHEDGES_gc);
     PORTD_PIN1CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);
     
     ADCA_Init_Advanced(_ADC_12bit, _ADC_INTERNAL_REF_VCC);
     
     Lcd_Init();
     Lcd_Cmd(_LCD_CLEAR);
     Lcd_Cmd(_LCD_CURSOR_OFF);
}
 
 
signed int adc_avg(unsigned char no_of_samples, unsigned char channel)
{
      signed long avg = 0;
      unsigned char samples = no_of_samples;
      
      while(samples > 0)
      {
          avg += ADCA_Get_Sample(channel);
          samples--;
      }
      avg /= no_of_samples;
      
      return avg;
}       
 
 
void lcd_print(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char cnt_volt)
{
     unsigned char tmp = 0;
 
     if(value > 0)
     {
         lcd_out(y_pos, x_pos, " ");
     }
     else
     {
         lcd_out(y_pos, x_pos, "-");
         value *= -1;
     }
 
     tmp = (value / 1000);
     lcd_chr_cp(tmp + 48);
     
     switch(cnt_volt)
     {
        case 1:
        {
            break;
        }
        default:
        {
            lcd_chr_cp(46);
            break;
        }
     }
     
     tmp = ((value / 100) % 10);
     lcd_chr_cp((tmp + 48));
     tmp = ((value / 10) % 10);
     lcd_chr_cp((tmp + 48));
     tmp = (value % 10);
     lcd_chr_cp((tmp + 48));
} 
 
 
float map(float v, float x_min, float x_max, float y_min, float y_max)
{
    float m = 0.0;
    m = ((y_max - y_min)/(x_max - x_min));
    return (y_min + (m * (v - x_min)));
}

MikroC Library (2) MikroC Library (1)

Video Link: https://www.youtube.com/watch?v=xB7MZZ9FFw4

 

XMega ADC Unsigned Single-Ended

 

#include <io.h>
#include <adc.h>
#include <clock.h>      
 
 
sbit LCD_RS at PORTC_OUT.B2;
sbit LCD_EN at PORTC_OUT.B3;
sbit LCD_D4 at PORTC_OUT.B4;
sbit LCD_D5 at PORTC_OUT.B5;
sbit LCD_D6 at PORTC_OUT.B6;
sbit LCD_D7 at PORTC_OUT.B7;
 
sbit LCD_RS_Direction at PORTC_DIR.B2;
sbit LCD_EN_Direction at PORTC_DIR.B3;
sbit LCD_D4_Direction at PORTC_DIR.B4;
sbit LCD_D5_Direction at PORTC_DIR.B5;
sbit LCD_D6_Direction at PORTC_DIR.B6;
sbit LCD_D7_Direction at PORTC_DIR.B7;
 
 
signed int offset = 0;
                      
 
void clock_setup();
void io_setup();
void adc_setup();
void setup();
signed int ADCA_read_ext_pins(unsigned char pin);
signed int adc_avg(unsigned char no_of_samples, unsigned char pin);
void lcd_print(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char cnt_volt);
float map(float v, float x_min, float x_max, float y_min, float y_max);
 
 
void main()
{
     signed int adc = 0;
     float v = 0;
 
     setup();
     
     lcd_out(1, 1, "V:");
     lcd_out(2, 1, "ADC:");
 
     while(1)
     {
              adc = adc_avg(25, ADC_CH_MUXPOS_PIN1_gc);
              v = map(adc, offset, 4095.0, 0, 1959.375);
 
              lcd_print(4, 1, v, 0);
              lcd_print(5, 2, adc, 1);
              delay_ms(600);
     };
}
 
 
void clock_setup()
{
     OSC_CTRL |= OSC_RC32KEN_bm;
     while(!(OSC_STATUS & OSC_RC32KRDY_bm));
     OSC_CTRL |= OSC_RC32MEN_bm;
     CPU_CCP = CCP_IOREG_gc;
     CLK_PSCTRL = ((CLK_PSCTRL & (~(CLK_PSADIV_gm | CLK_PSBCDIV1_bm | CLK_PSBCDIV0_bm)))
                  | CLK_PSADIV_1_gc | CLK_PSBCDIV_2_2_gc);
     OSC_DFLLCTRL = ((OSC_DFLLCTRL & (~(OSC_RC32MCREF_gm | OSC_RC2MCREF_bm))) |
                    OSC_RC32MCREF_RC32K_gc);
     DFLLRC32M_CTRL |= DFLL_ENABLE_bm;
     while(!(OSC_STATUS & OSC_RC32MRDY_bm));
     CPU_CCP = CCP_IOREG_gc;
     CLK_CTRL = ((CLK_CTRL & (~CLK_SCLKSEL_gm)) | CLK_SCLKSEL_RC32M_gc);
     OSC_CTRL &= (~(OSC_RC2MEN_bm | OSC_XOSCEN_bm | OSC_PLLEN_bm));
     PORTCFG_CLKEVOUT = 0x00;
}
 
 
void io_setup()
{
     PORTA_OUT = 0x00;
     PORTA_DIR = 0x00;
     PORTCFG_MPCMASK = 0xFF;
     PORTA_PIN0CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);
     PORTA_INTCTRL = 0x00;
     PORTA_INT0MASK = 0x00;
     PORTA_INT1MASK = 0x00;
}
 
 
void adc_setup()
{
     unsigned char samples = 16;
 
     ADCA_CAL = (0x0FFF & ((PROD_SIGNATURES_ADCACAL1 << 8) | PROD_SIGNATURES_ADCACAL0));
     ADCA_CTRLB = ((1 << ADC_IMPMODE_bp) | ADC_CURRLIMIT_NO_gc | (0 << ADC_CONMODE_bp) | ADC_RESOLUTION_12BIT_gc);
     ADCA_PRESCALER = ADC_PRESCALER_DIV64_gc;
     ADCA_REFCTRL = (ADC_REFSEL_VCC_gc | (0 << ADC_TEMPREF_bp) | (0 << ADC_BANDGAP_bp));
     ADCA_CH0_CTRL = ((0 << ADC_CH_START_bp) | ADC_CH_INPUTMODE_SINGLEENDED_gc);
     ADCA_CH0_MUXCTRL = ADC_CH_MUXPOS_PIN0_gc;
     ADCA_CTRLA |= ADC_ENABLE_bm;
     delay_ms(4);
 
     while(samples > 0)
     {
        ADCA_CH0_CTRL |= (1 << ADC_CH_START_bp);
        while(!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm));
        ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm;
        offset += ADCA_CH0RES;
        samples--;
     }  
 
     ADCA_CTRLA &= ~ADC_ENABLE_bm;
     offset >>= 4;
     ADCA_CMP = 0x0000;
     ADCA_CH0_CTRL = ((0 << ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_SINGLEENDED_gc);
     ADCA_CH0_MUXCTRL = ADC_CH_MUXPOS_PIN1_gc;
     ADCA_EVCTRL = (ADC_SWEEP_0_gc | ADC_EVACT_NONE_gc);
     ADCA_CH0_INTCTRL = (ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc);
     ADCA_CH1_INTCTRL = ADC_CH_INTLVL_OFF_gc;
     ADCA_CH2_INTCTRL = ADC_CH_INTLVL_OFF_gc;
     ADCA_CH3_INTCTRL = ADC_CH_INTLVL_OFF_gc;
     ADCA_CTRLB |= ADC_FREERUN_bm;
     ADCA_CTRLA |= ADC_ENABLE_bm;
     delay_ms(9);
}
 
 
void setup()
{
     clock_setup();
     io_setup();
     adc_setup();
     Lcd_Init();
     Lcd_Cmd(_LCD_CLEAR);
     Lcd_Cmd(_LCD_CURSOR_OFF);
}
 
 
signed int ADCA_read_ext_pins(unsigned char pin)
{
    signed int val = 0;
 
    ADCA_CH0_MUXCTRL = pin;
    while(!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm));
    ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm;
    val = ADCA_CH0_RES;
 
    return val;
}
 
 
signed int adc_avg(unsigned char no_of_samples, unsigned char pin)
{
      signed long avg = 0;
      unsigned char samples = no_of_samples;
 
      while(samples > 0)
      {
          avg += ADCA_read_ext_pins(pin);
          samples--;
      }
      avg /= no_of_samples;
      
      return avg;
}
 
 
void lcd_print(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char cnt_volt)
{
     unsigned char tmp = 0;
 
     if(value > 0)
     {
         lcd_out(y_pos, x_pos, " ");
     }
     else
     {
         lcd_out(y_pos, x_pos, "-");
         value *= -1;
     }
 
     tmp = (value / 1000);
     lcd_chr_cp(tmp + 48);
     
     switch(cnt_volt)
     {
        case 1:
        {
            break;
        }
        default:
        {
            lcd_chr_cp(46);
            break;
        }
     }
     
     tmp = ((value / 100) % 10);
     lcd_chr_cp((tmp + 48));
     tmp = ((value / 10) % 10);
     lcd_chr_cp((tmp + 48));
     tmp = (value % 10);
     lcd_chr_cp((tmp + 48));
}   
 
 
float map(float v, float x_min, float x_max, float y_min, float y_max)
{
    float m = 0.0;
    m = ((y_max - y_min)/(x_max - x_min));
    return (y_min + (m * (v - x_min)));

}
Unsigned single -ended (2) Unsigned single -ended (1)

Video Link: https://www.youtube.com/watch?v=4v042tw5IQY

XMega ADC Signed Single-Ended

 

#include <io.h>
#include <adc.h>
#include <clock.h>
 
 
sbit LCD_RS at PORTC_OUT.B2;
sbit LCD_EN at PORTC_OUT.B3;
sbit LCD_D4 at PORTC_OUT.B4;
sbit LCD_D5 at PORTC_OUT.B5;
sbit LCD_D6 at PORTC_OUT.B6;
sbit LCD_D7 at PORTC_OUT.B7;
 
sbit LCD_RS_Direction at PORTC_DIR.B2;
sbit LCD_EN_Direction at PORTC_DIR.B3;
sbit LCD_D4_Direction at PORTC_DIR.B4;
sbit LCD_D5_Direction at PORTC_DIR.B5;
sbit LCD_D6_Direction at PORTC_DIR.B6;
sbit LCD_D7_Direction at PORTC_DIR.B7; 
 
 
signed int offset = 0;
 
 
void clock_setup();
void io_setup();
void adc_setup();
void setup();
signed int ADCA_read_ext_pins(unsigned char pin);
signed int adc_avg(unsigned char no_of_samples, unsigned char pin);
void lcd_print(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char cnt_volt);
 
 
void main()
{
     signed int adc = 0;
     float v = 0;
 
     setup();
     
     lcd_out(1, 1, "V:");
     lcd_out(2, 1, "ADC:");
 
     while(1)
     {
              adc = adc_avg(25, ADC_CH_MUXPOS_PIN7_gc);
 
              v = ((adc * 2062.5) / 2047);
 
              lcd_print(6, 1, v, 0);
              lcd_print(6, 2, adc, 1);
              delay_ms(600);
     };
}
 
 
void clock_setup()
{
     OSC_CTRL |= OSC_RC32KEN_bm;
     while(!(OSC_STATUS & OSC_RC32KRDY_bm));
     OSC_CTRL |= OSC_RC32MEN_bm;
     CPU_CCP = CCP_IOREG_gc;
     CLK_PSCTRL = ((CLK_PSCTRL & (~(CLK_PSADIV_gm | CLK_PSBCDIV1_bm | CLK_PSBCDIV0_bm)))
                  | CLK_PSADIV_1_gc | CLK_PSBCDIV_2_2_gc);
     OSC_DFLLCTRL = ((OSC_DFLLCTRL & (~(OSC_RC32MCREF_gm | OSC_RC2MCREF_bm))) |
                    OSC_RC32MCREF_RC32K_gc);
     DFLLRC32M_CTRL |= DFLL_ENABLE_bm;
     while(!(OSC_STATUS & OSC_RC32MRDY_bm));
     CPU_CCP = CCP_IOREG_gc;
     CLK_CTRL = ((CLK_CTRL & (~CLK_SCLKSEL_gm)) | CLK_SCLKSEL_RC32M_gc);
     OSC_CTRL &= (~(OSC_RC2MEN_bm | OSC_XOSCEN_bm | OSC_PLLEN_bm));
     PORTCFG_CLKEVOUT = 0x00;
}
 
 
void io_setup()
{
     PORTA_OUT = 0x00;
     PORTA_DIR = 0x00;
     PORTCFG_MPCMASK = 0xFF;
     PORTA_PIN0CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);
     PORTA_INTCTRL = 0x00;
     PORTA_INT0MASK = 0x00;
     PORTA_INT1MASK = 0x00;
}
 
 
void adc_setup()
{
     unsigned char samples = 16;
 
     ADCA_CAL = (0x0FFF & ((PROD_SIGNATURES_ADCACAL1 << 8) | PROD_SIGNATURES_ADCACAL0));
     
     ADCA_CTRLB = ((0 << ADC_IMPMODE_bp) | ADC_CURRLIMIT_NO_gc | (1 << ADC_CONMODE_bp) | ADC_RESOLUTION_12BIT_gc);
     ADCA_PRESCALER = ADC_PRESCALER_DIV64_gc;
     ADCA_REFCTRL = (ADC_REFSEL_VCC_gc | (0 << ADC_TEMPREF_bp) | (0 << ADC_BANDGAP_bp));
     ADCA_CH0_CTRL = ((0 << ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc);
     ADCA_CH0_MUXCTRL = (ADC_CH_MUXPOS_PIN0_gc | ADC_CH_MUXNEG_PIN0_gc);
     ADCA_CTRLA |= ADC_ENABLE_bm;
     delay_ms(4);
 
     while(samples > 0)
     {
        ADCA_CH0_CTRL |= (1 << ADC_CH_START_bp);
        while(!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm));
        ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm;
        offset += ADCA_CH0RES;
        samples--;
     }
 
     ADCA_CTRLA &= ~ADC_ENABLE_bm;
     offset >>= 4;
     ADCA_CMP = 0x0000;
     ADCA_CH0_CTRL = ((0 << ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_SINGLEENDED_gc);
     ADCA_CH0_MUXCTRL = ADC_CH_MUXPOS_PIN7_gc;
     ADCA_EVCTRL = (ADC_SWEEP_0_gc | ADC_EVACT_NONE_gc);
     ADCA_CH0_INTCTRL = (ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc);
     ADCA_CH1_INTCTRL = ADC_CH_INTLVL_OFF_gc;
     ADCA_CH2_INTCTRL = ADC_CH_INTLVL_OFF_gc;
     ADCA_CH3_INTCTRL = ADC_CH_INTLVL_OFF_gc;
     ADCA_CTRLB |= ADC_FREERUN_bm;
     ADCA_CTRLA |= ADC_ENABLE_bm;
     delay_ms(9);
}
 
 
void setup()
{
     clock_setup();
     io_setup();
     adc_setup();
     Lcd_Init();
     Lcd_Cmd(_LCD_CLEAR);
     Lcd_Cmd(_LCD_CURSOR_OFF);
}
 
 
signed int ADCA_read_ext_pins(unsigned char pin)
{
    signed int val = 0;
 
    ADCA_CH0_MUXCTRL = pin;
    while (!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm));
    ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm;
    val = ADCA_CH0_RES;
    
    if (val > offset)
    {
       val -= offset;
    }
    else
    {
       val = 0;
    }
    
    return val;
}
 
 
signed int adc_avg(unsigned char no_of_samples, unsigned char pin)
{
      signed long avg = 0;
      unsigned char samples = no_of_samples;
 
      while(samples > 0)
      {
          avg += ADCA_read_ext_pins(pin);
          samples--;
      }
      avg /= no_of_samples;
      
      return avg;
}
 
 
void lcd_print(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char cnt_volt)
{
     unsigned char tmp = 0;
 
     if(value > 0)
     {
         lcd_out(y_pos, x_pos, " ");
     }
     else
     {
         lcd_out(y_pos, x_pos, "-");
         value *= -1;
     }
 
     tmp = (value / 1000);
     lcd_chr_cp(tmp + 48);
     
     switch(cnt_volt)
     {
        case 1:
        {
            break;
        }
        default:
        {
            lcd_chr_cp(46);
            break;
        }
     }
     
     tmp = ((value / 100) % 10);
     lcd_chr_cp((tmp + 48));
     tmp = ((value / 10) % 10);
     lcd_chr_cp((tmp + 48));
     tmp = (value % 10);
     lcd_chr_cp((tmp + 48));
}

Signed single ended (1) Signed single ended (2) 

Video Link: https://www.youtube.com/watch?v=xC43v_35zRA

 

XMega ADC Differential Conversion Mode

 

#include <io.h>
#include <adc.h>
#include <clock.h>
 
 
sbit LCD_RS at PORTC_OUT.B2;
sbit LCD_EN at PORTC_OUT.B3;
sbit LCD_D4 at PORTC_OUT.B4;
sbit LCD_D5 at PORTC_OUT.B5;
sbit LCD_D6 at PORTC_OUT.B6;
sbit LCD_D7 at PORTC_OUT.B7;
 
sbit LCD_RS_Direction at PORTC_DIR.B2;
sbit LCD_EN_Direction at PORTC_DIR.B3;
sbit LCD_D4_Direction at PORTC_DIR.B4;
sbit LCD_D5_Direction at PORTC_DIR.B5;
sbit LCD_D6_Direction at PORTC_DIR.B6;
sbit LCD_D7_Direction at PORTC_DIR.B7;
 
 
signed int offset = 0;
 
 
void clock_setup();
void io_setup();
void adc_setup();
void setup();
signed int ADCA_read_ext_pins(unsigned char pos_pin, unsigned char neg_pin);
signed int adc_avg(unsigned char no_of_samples, unsigned char pos_pin, unsigned char neg_pin);
void lcd_print(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char cnt_volt);
 
 
void main()
{
     signed int adc = 0;
     float v = 0;
 
     setup();
     
     lcd_out(1, 1, "V:");
     lcd_out(2, 1, "ADC:");
 
     while(1)
     {
              adc = adc_avg(20, ADC_CH_MUXPOS_PIN1_gc, ADC_CH_MUXNEG_PIN2_gc);
              v = ((adc * 2062.5) / 2048);
 
              lcd_print(6, 1, v, 0);
              lcd_print(6, 2, adc, 1);
              delay_ms(600);
     };
}
 
 
void clock_setup()
{
     OSC_CTRL |= OSC_RC32KEN_bm;
     while(!(OSC_STATUS & OSC_RC32KRDY_bm));
     OSC_CTRL |= OSC_RC32MEN_bm;
     CPU_CCP = CCP_IOREG_gc;
     CLK_PSCTRL = ((CLK_PSCTRL & (~(CLK_PSADIV_gm | CLK_PSBCDIV1_bm | CLK_PSBCDIV0_bm)))
                  | CLK_PSADIV_1_gc | CLK_PSBCDIV_2_2_gc);
     OSC_DFLLCTRL = ((OSC_DFLLCTRL & (~(OSC_RC32MCREF_gm | OSC_RC2MCREF_bm))) |
                    OSC_RC32MCREF_RC32K_gc);
     DFLLRC32M_CTRL |= DFLL_ENABLE_bm;
     while(!(OSC_STATUS & OSC_RC32MRDY_bm));
     CPU_CCP = CCP_IOREG_gc;
     CLK_CTRL = ((CLK_CTRL & (~CLK_SCLKSEL_gm)) | CLK_SCLKSEL_RC32M_gc);
     OSC_CTRL &= (~(OSC_RC2MEN_bm | OSC_XOSCEN_bm | OSC_PLLEN_bm));
     PORTCFG_CLKEVOUT = 0x00;
}
 
 
void io_setup()
{
     PORTA_OUT = 0x00;
     PORTA_DIR = 0x00;
     PORTCFG_MPCMASK = 0xFF;
     PORTA_PIN0CTRL = (PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc);
     PORTA_INTCTRL = 0x00;
     PORTA_INT0MASK = 0x00;
     PORTA_INT1MASK = 0x00;
}
 
 
void adc_setup()
{
     unsigned char samples = 16;
 
     ADCA_CAL = (0x0FFF & ((PROD_SIGNATURES_ADCACAL1  << 8) | PROD_SIGNATURES_ADCACAL0));
     ADCA_CTRLB = ((1 << ADC_IMPMODE_bp) | ADC_CURRLIMIT_NO_gc | (1 << ADC_CONMODE_bp) | ADC_RESOLUTION_12BIT_gc);
     ADCA_PRESCALER = ADC_PRESCALER_DIV64_gc;
     ADCA_REFCTRL = (ADC_REFSEL_VCC_gc | (0 << ADC_TEMPREF_bp) | (0 << ADC_BANDGAP_bp));
     ADCA_CH0_CTRL = ((0 << ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc);
     ADCA_CH0_MUXCTRL = (ADC_CH_MUXPOS_PIN0_gc | ADC_CH_MUXNEG_PIN0_gc);
     ADCA_CTRLA |= ADC_ENABLE_bm;
     delay_ms(4);
 
     while(samples > 0)
     {
        ADCA_CH0_CTRL |= (1 << ADC_CH_START_bp);
        while(!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm));
        ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm;
        offset += ADCA_CH0RES;
        samples--;
     }
 
     ADCA_CTRLA &= ~ADC_ENABLE_bm;
     offset >>= 4;
     ADCA_CH0_CTRL = ((0 << ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_DIFF_gc);
     ADCA_CH0_MUXCTRL = (ADC_CH_MUXPOS_PIN1_gc | ADC_CH_MUXNEG_PIN2_gc);
     ADCA_EVCTRL = (ADC_SWEEP_0_gc | ADC_EVACT_NONE_gc);
     ADCA_CH0_INTCTRL = (ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc);
     ADCA_CH1_INTCTRL = ADC_CH_INTLVL_OFF_gc;
     ADCA_CH2_INTCTRL = ADC_CH_INTLVL_OFF_gc;
     ADCA_CH3_INTCTRL = ADC_CH_INTLVL_OFF_gc;
     ADCA_CTRLB |= ADC_FREERUN_bm;
     ADCA_CTRLA |= ADC_ENABLE_bm;
     delay_ms(9);
}
 
 
void setup()
{
     clock_setup();
     io_setup();
     adc_setup();
     Lcd_Init();
     Lcd_Cmd(_LCD_CLEAR);
     Lcd_Cmd(_LCD_CURSOR_OFF);
}
 
 
signed int ADCA_read_ext_pins(unsigned char pos_pin, unsigned char neg_pin)
{
    signed int val = 0;
 
    ADCA_CH0_MUXCTRL = (pos_pin | neg_pin);
    while (!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm));
    ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm;
    val = ADCA_CH0_RES;
    val -= offset;
    
    return val;
}
 
 
signed int adc_avg(unsigned char no_of_samples, unsigned char pos_pin, unsigned char neg_pin)
{
      signed long avg = 0;
      unsigned char samples = no_of_samples;
 
      while(samples > 0)
      {
          avg += ADCA_read_ext_pins(pos_pin, neg_pin);
          samples--;
      }
      avg /= no_of_samples;
      
      return avg;
}
 
 
void lcd_print(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char cnt_volt)
{
     unsigned char tmp = 0;
 
       if(value > 0)
       {
           lcd_out(y_pos, x_pos, " ");
       }
       else
       {
           lcd_out(y_pos, x_pos, "-");
           value *= -1;
       }
 
       tmp = (value / 1000);
       lcd_chr_cp(tmp + 48);
       
       switch(cnt_volt)
       {
          case 1:
          {
              break;
          }
          default:
          {
              lcd_chr_cp(46);
              break;
          }
       }
       
       tmp = ((value / 100) % 10);
       lcd_chr_cp((tmp + 48));
       tmp = ((value / 10) % 10);
       lcd_chr_cp((tmp + 48));
       tmp = (value % 10);
       lcd_chr_cp((tmp + 48));
}

Differental (2) Differental (1)

Video Link: https://www.youtube.com/watch?v=eiordbwrI0s

As always it is not always possible to show everything of a sophisticated MCU like the XMega in such a short discussion and so I leave some things for the reader. I didn’t show the following things in this post:

  • ADC + DMA use
  • ADC + event system
  • ADC’s temperature compensation functionality
  • ADC sweeping
  • How virtual channels work
  • ADC’s compare functionality
  • ADC interrupt
  • Differential ADC with gain as it is similar to differential ADC mode.

I believe if you understood the basic of XMega ADC then these are not die-hard issues. ADC of such a MCU is really both robust and sophisticated. Manufacturers try to give literally everything that users imagine and there sophistication emerges. I recommend going through Atmel’s official docs, especially the reference manual as they will help a lot. To be honest, I read several blogs and even visited sites like AVR Freaks beside Atmel’s docs only to see that people are way too lazy to think beyond the boundaries of Atmel’s ASF. Though the ASF has made life easier, it is doesn’t help raw level coders like me in many ways.

 

Files: XMega ADC.

 

Happy coding.

Author: Shawon M. Shahryiar

https://www.facebook.com/groups/microarena/  

https://www.facebook.com/MicroArena 

+8801970046495                                                                                                    30.10.2014

 


Introducing Easy Matrix: A cascadable 8×8 LED dot matrix display module

$
0
0

Easy Matrix is an easily cascadable 8×8 monochromatic LED dot matrix display module with onboard MAXIM’s MAX7219 LED driver chip. The MAX7219 allows you to drive the LED matrix using only three I/O pins of Arduino or any other microcontroller. The LED matrix module used in Easy Matrix has a bigger dot size (5mm) and has the overall display dimensions of 60.2mm x 60.2mm (2.4″x2.4″). It is easily cascadable in series with the help of precisely aligned male and female header pairs located on the left and right sides of the display module. With lots of freely available Arduino libraries for MAX7219 chip, this module is easy to use in any Arduino project for displaying basic text and animation.

Easy Matrix: Cascadable LED matrix display module

Easy Matrix: Cascadable LED matrix display module

Description

The Easy Matrix PCB dimensions are 60.5mm (2.4″) x 75.0mm (2.95″) and has 3.5mm mounting holes at its four corners. It uses a male (J1) and female (J2) headers for cascading multiple modules in series. The MAX7219 data input and control signals are accessible through J1 header on right side. The J2 header provides the MAX7219 serial data output and control signals to another Easy Matrix module cascaded to its left. Two 1×8 female headers are used as sockets to hold the LED matrix module with A-type polarity, which means the rows are common-anodes and the columns are common-cathodes. The picture below shows an Easy Matrix display PCB with all the electronics components assembled. One of the header socket is marked with a “circle with 1” to indicate where the pin number 1 of the LED matrix display should be inserted.

EasyMatrixDim

Easy Matrix display board components

Easy Matrix module

Easy Matrix module

Features

Four Easy Matrix modules cascaded together and driven by Arduino Uno

Four Easy Matrix modules cascaded together and driven by Arduino Uno

Demo project: Portable Bluetooth-enabled Scrolling LED Matrix Display

Easy Matrix Kit buying link

Kit assembly instructions

le

Scrolling LED matrix demo

Water softener salt level monitor

$
0
0

Hard water contains more minerals (calcium and magnesium) than ordinary water. Although it is non-toxic, it is less desirable as it can clog water pipes and complicate soap and detergent dissolving in water. It also builds up scales in water heaters over time, thus shortening their operational lifetime. In residential units, hard water is usually softened by installing a water softener unit connected directly to the water supply line. The water softner exchanges salt for the dissolved minerals, which results in softer water. David Cook’s water softener appliance stores the salt supply in a brine tank, which requires refilling in every few weeks. Until now, the only way Dave could know that the tank is empty was when his wife complained that the dishwasher, soap or shampoo was not working. So, for uninterrupted water softening, Dave has made a salt level monitor for the brine tank. The device uses a 10-element LED array to indicate the salt level in the tank. He used an infrared sensor to measure the salt level in the tank. This data is processed by an AVR ATtiny861 microcontroller and displayed it on the LED bargraph. A light-dependent resistor is also implemented in the project as a smart switch to save battery power. The LED bar graph display is auto-turned off until the room lights are turned on or somebody approaches the monitor panel, which changes the room brightness level.

Water softener salt level monitor

Water softener salt level monitor

Animated robot mask for halloween

$
0
0

I hope all of you had a wonderful and safe Halloween. Ours was great. We had a lot of fun taking out our 3-year old son, who dressed up like Curious George (his favorite cartoon character), for trick or treat in our neighborhood. The most difficult part of Halloween is choosing costumes for kids. We all want to do something different every year. And so did [melarky], who made a pretty neat animated robot mask for his oldest son to wear on Halloween this year. His robot mask uses Adafruit’s neopixel rings for robot eyes, an old iPhone running MouthOff app for its mouth part, and a cheap voice changer toy to add some audio effects. The neopixel rings are controlled by an Arduino board for creating animated eyes.

Animated robot mask for Halloween

Animated robot mask for Halloween

 

Remote motion sensing and triggering for your DSLR

$
0
0

We have seen Angelo making a homebrew USB condenser mic and piezoelectric power generator shoes before, both of which were kind of cool projects. Now he has come up with a remote motion sensing and triggering for a DSLR camera utilizing his favorite tool, Arduino. He proposed the applications of this project in wildlife photography, sports, and home security systems to take automatic photo shots when motion is sensed. 

His project has two main units. The first one is a Motion Sensing Beacon, which is located at a remote area where the motion activities are to be monitored. It consists of a PIR motion sensor, Arduino, and a 433MHz RF transmitter module. When motion is detected, the Arduino informs the second unit, Remote Receiver and Controller, which consists of a 433MHz RF receiver, another Arduino, and camera trigger system. The camera is aimed at the same location that is being monitored for motion activities. When the Remote Receiver unit receives the go signal, it activates the camera to take multiple shots of the location.

Remote motion sensing and camera triggering device

Remote motion sensing and camera triggering device

Raspberry Pi powered dual-player arcade

$
0
0

Who wouldn’t want an Arcade at home? Check out this neatly home-built dual player arcade machine powered by Raspberry Pi from rolfebox. This plays multiple types of retro games, including NES, SNES, Megadrive and MAME games. The author shares the details of this built on the original Instructables page.

Raspberry Pi-powered dual player arcade

Raspberry Pi-powered dual player arcade

DIY motion activated camera

$
0
0

Whether you are aiming to monitor your pets’ activities at home when you are gone or to surveil a particular location at your house or office, this DIY motion activated camera might be helpful to serve your purpose. The primary components used to build this camera are Raspberry Pi, Raspberry Pi camera module, PIR motion sensor, and USB WiFi adapter. The camera automatically takes still shots or record short videos when a motion is detected in the frame range of the camera. In addition, the photos and videos are automatically uploaded to the user’s Dropbox account for remote access.

Motion sensing camera

Motion sensing camera

DIY audio/video transport control surface

$
0
0

Audio/video transport controllers are used in recording studios and live performance setups for quick hands-on control on demanding editing or mixing tasks. These devices are an expensive piece of hardware (costs from a few hundreds to thousands of USD). Victor Frost’s OpenTransport project would allow hobbyists to build an external transport control surface at very low price. It is an open-source, open hardware transport controller that sends out MIDI commands and therefore, works with most of the Digital Audio Workstation and Digital Video Workstation softwares. It is Arduino-powered and provides controls for play, stop, fast forward, rewind, record, loop, and mackie keys Function 1 and Function 2, which are configurable.

OpenTransport: An open-source control surface

OpenTransport: An open-source control surface

 


Arduino multitasking guide

$
0
0

Bill Earl’s new tutorial on Adafruit is about multitasking with Arduino where he explains practically how to program an Arduino board to perform multiple independent tasks without the processor being tied up to any kind of delay. His approach define each task as an independent state machine which can execute without affecting or being affected by the others.

Arduino multi-tasking

Arduino multi-tasking

Capacitive touch sensing demo

$
0
0

Capacitive touch sensing allows to provide digital inputs with a simple touching of electrodes. In Arduino, the capacitiveSensor library can be used to convert two or more of its I/O pins into a capacitive sensor. This technique requires external resistors and metal foils to work properly. This Instructable describes a physical setup for making five capacitive touch sensors with the Arduino I/O pins.

Capacitive touch sensing with Arduino

Capacitive touch sensing with Arduino

 

Cloud-connected automatic solar tracker

$
0
0

The use of solar tracking systems allows the solar panels to track the course of Sun during the day time and ensures that the panels are receiving maximum solar input. A photovoltaic system with a solar tracker can boost the output power by 20-40%, compared to a fixed installation. While there are lots of resources available on internet on solar trackers, this particular solar tracking system is unique in the sense that it offers lot more connectivity and other fancy features than just tracking the Sun. It is built to drive a 90 Watts solar panel with azimuth and elevation control using two step motors. The project is controlled with Electric Imp, which derives the inclination and azimuth angle of the solar panel using a 6-axis accelerometer/magnetometer. The use of Electric Imp also allows internet cloud connectivity to the  project.

Cloud-connected solar tracker

Cloud-connected solar tracker

 

Raspberry Pi FM transmitter

$
0
0

Do you know you can make your Raspberry Pi play your favorite music over an FM radio with a very little effort? Yes, all you need to make this FM radio transmitter is a Raspberry Pi, an SD card, a power supply, and a small piece of wire to serve as antenna. You can load your audio files into the SD card and choose your transmission frequency in the commercial FM band. The PirateRadio.py python script generates frequency-modulated radio waves on the Raspberry Pi GPIO pin 4, which are injected into air with a short wire connected to it.

Raspberry Pi FM transmitter

Raspberry Pi FM transmitter

The post Raspberry Pi FM transmitter appeared first on Embedded Lab.

Alphanumeric LED display for web data

$
0
0

This 8-character alphanumeric LED display project connects to an USB port of PC and can display any data from your computer or from web such as weather info, RSS feeds from your favorite websites, time, and anything else that you would like to. The display has 8 push button for user interface to quickly navigate through various functionalities. A PC application developed in C# is used to configure the display. The display uses the PIC18F4550 microcontroller and its firmware is developed using MPLAB IDE using C18 compiler.

Alphanumeric LED display for web info

Alphanumeric LED display for web info

Visit the author’s page for schematics, software, and other details.

The post Alphanumeric LED display for web data appeared first on Embedded Lab.

Raspberry Pi Mediabox

$
0
0

MrLeeh’s Raspbmc Mediabox multimedia player uses a 7″ LCD for user interface, and is controlled by Raspberry Pi running Raspbmc, a minimal Linux distribution based on Debian for turning Raspberry Pi into an XBMC player. It can be controlled through an IR remorte, a web interface, a smartphone or tablet.

Raspberry Pi Mediabox

Raspberry Pi Mediabox

The post Raspberry Pi Mediabox appeared first on Embedded Lab.

Arduino pin monitor shield

$
0
0

Carsten Tonn-Petersen has designed this Arduino pin monitor and tester shield to assist his prototyping work with Arduino. The key features of this shield is it provides one LED for every single I/O pin and can be used with Arduino Uno, Leonardo, Mega, Due, and Mini. The shield also features one tact switch and one toggle switch for digital inputs along with two potentiometers for simulating analog input voltages during prototyping.

Arduino tester shield

Arduino tester shield

The complete list of features as Carsten has mentioned about his Arduino pin monitor and tester shield are listed below:

  • One LED for every single input or output
  • Can be used with Uno, Leonardo, Mega, Due, Mini, etc.
  • Also fits with my universal I/O board
  • Power taken from Arduino 5V and 3.3V outputs, and the Vin
  • Load on any pin is 10 kohm or more
  • LED intensity proportionally reflects the pin voltage or duty cycle
  • Builtin inputs and outputs for testing new ideas:
    • One pushbutton (P) to digital input
    • One toggle switch (T) to digital input
    • Two potentiometers (1, 2) to two analog inputs
    • 4 digital outputs to 7-segment number display (e.g. for program STATE output)
    • Very small moving coil voltmeter on PWM output
    • Piezo loudspeaker on PWM output
    • 4 digital outputs to open-drain MOSFET (builtin flyback diodes)
    • One opto-isolated digital input
    • One opto-isolated digital output (not for 230 VAC)
    • One direct analog input via miniature LEMO coax connector
    • One direct digital I/O/PWM via miniature LEMO coax connector
    • One reed-relay (no coil) to digital input
    • One mercury shake alarm to digital input
    • One TMP36 temperature sensor to analog input
    • One electret microphone to analog input (x 100 gain)
    • One NTC resistor to analog input (linearized)
    • One light-dependant resistor to analog input
  • All inputs and outputs can be made passive to enable inputs from other sources
  • LED’s grouped in 16 for analog I/O, 14 for digital I/O/PWM, 8 for digital I/O/Tx/Rx and 32 digital I/O. In total 70 LEDs.
  • All LEDs are very high efficiency white SMD types with coloured film on top, according to the group.
  • The LEDs cathode reference can be adjusted down to -2V: LEDs will start to light up when pin voltage goes positive.
  • The cathode reference is divided into one for analog and one for digital, adjusted individually
  • Maximum input voltages can be selected between 5V or 3.3V to fit with DUE board
  • Voltage for internal circuits and steppermotor outputs can be selected between 5V and Vin
  • IC-sockets and Arduino pins are all gold plated
  • LEMO I/O, Shake-sensor, NTC, TMP36, microphone and piezo-speaker are in a detachable separate module

Visit Carsten’s project page for more details.

The post Arduino pin monitor shield appeared first on Embedded Lab.


Mobile Sun-seeker for indoor planters

$
0
0

Indoor plants are great for adding some greenery to home interior decoration. Most of the time low-lighting conditions can sustain indoor plants. However, it is still important that they get proper sunlight for healthy and greenish growth. If you have windows in more than one direction of your house, it is possible that the sunniest spot inside your house is not always the same during the course of day. This mobile sun-seeker robot helps to navigate the interior plants to enjoy the sunniest spot in the house.

The mobile sun-seeker uses two continuous rotation servos to move around and are controlled by an Arduino nano board. Two 6V solar panels are used in two opposite sides of plant to detect the incident sunlight. The sum of the two solar cell readings is used to compute the overall sunniness of a particular location. The sun-seeker robot also uses two ultrasonic range detectors to avoid running into other objects or falling off the edges.

Mobile sun-seeker robot

Mobile sun-seeker robot

 

The post Mobile Sun-seeker for indoor planters appeared first on Embedded Lab.

Order your favorite pizza with just the push of a button

$
0
0

Hungry pizza-lover yet excessively lethargic to pick up the phone or use an app to order online? Don’t worry, this Emergency Pizza button will let you instantly order a pizza full of your favorite toppings with the simple push of the button. The Pizza Button uses the BeagleBone Black microcontroller board which does all of web scrapping for you behind the screen. When the button is pressed, the web scraper can log into your Grub Hub account and order a pizza from your favorite online store (the author has programmed it for making online order from San Francisco North Beach Pizza).

The Python application for Pizza Button interacts with webpages through Selenium, which is a software tool for automating web browsing. To further enhance the browsing experience, the application incorporates the PhantomJS headless browser. A headless browser is a GUI-less web browser, not meant for displaying content to users, that accesses web pages and provides their contents to other programs. The combination of all these tools together facilitates the Pizza Button to login to your personal GrubHub account, browse through the menu of your favorite online pizza store, and orders a pizza of your choice. It all happens with just the push of the button.

Emergency pizza button

Emergency pizza button

The post Order your favorite pizza with just the push of a button appeared first on Embedded Lab.

Motion Sensing Pumpkin Vibrobot

$
0
0

Mechanical Engineer and K-12 STEM educator, Ben Finio, has designed this kid-friendly motion sensing pumpkin Bot, which could be a fun project to make for the next Halloween. The thing I liked the most about this PumpkinBot is its simplicity and microcontroller-free design. His motion-sensing bot uses a passive infrared (PIR) sensor attached in front of the pumpkin to detect motion. Three toothbrush heads are glued underneath the PumpkinBot to give it a stable tripod. When a motion is sensed, it triggers the robot’s LED eyes and a DC motor attached on its back. A wine cork fixed to the motor shaft create vibrations that are strong enough to move the robot around. It works best on a flat and smooth surface. You can leave it on your porch and watch enjoying the PumpkinBot scaring trick-or-treaters as they approach to your door.

Motion sensing pumpkin robot

Motion sensing pumpkin robot

The post Motion Sensing Pumpkin Vibrobot appeared first on Embedded Lab.

Mooltipass: An offline password keeper

$
0
0

In today’s digital world, password management has become an indispensable and challenging part of our lives. No matter is it our online banking, social media, email, restaurant, utilities, or remote server account, every web-interaction these days requires you to create a strong, non-repetitive, and frequently-changed  password to login to the system. With growing number of online accounts and their strong password policies, keeping track of the passwords is getting annoying and harder. Choosing the same password for multiple accounts puts your entire online identity at risk if that password is compromised. To address this password problem, Hackaday introduces a new piece of open-source hardware, called Mooltipass, which is a secure offline password keeper.

Mooltipass can generate and safely store strong and unique passwords for each website you use. It is a standalone USB device compatible with PCs, MACs, and smartphones, and emulates a standard USB keyboard when connected. When you visit a website and login is required, it enters your credentials with your confirmation. A personal PIN-locked smartcard is used to store the encryption key for your credentials, thus making sure that only you can get access to them. Last but not least, the Mooltipass offline password keeper also contains plugin headers to incorporate standard Arduino shields to further expand its capabilities.

To get Mooltipass into mass production, Hackaday is currently running a crowd-funding campaign on Indiegogo with half of the target ($109,112) being already made in a week. Good luck to the Mooltipass team for the success of their campaign.

Mooltipass, an offline password keeper

Mooltipass, an offline password keeper

The post Mooltipass: An offline password keeper appeared first on Embedded Lab.

Microchip announces new 16-bit A/D converters with 200Msps sampling rate

$
0
0

Microchip Technology Inc. has announced two families of new high-speed A/D converters in the MCP37DX1-200 and MCP372X1-200 families. These families feature 12-, 14- and 16-bit pipelined A/D converters with a maximum sampling rate of 200 Mega samples per second (Msps). The 14- and 16-bit devices feature high accuracy of over 74 dB Signal-to-Noise Ratio (SNR) and over 90 dB Spurious Free Dynamic Range (SFDR), while the 12-bit devices have 71.3 dB SNR and 90 dB SFDR. This enables high-precision measurements of fast input signals. These families operate at very low-power consumption of 490 mW at 200 Msps including LVDS digital I/O. Lower power-saving modes are available at 80 mW for standby and 33 mW for shutdown.

The MCP37DX1-200 and MCP372X1-200 include various digital processing features that simplify system design, cost and power usage for designers. These families also include decimation filters for improved SNR, individual phase, offset and gain adjustment and a fractional delay recovery for time-delay corrections in multi-channel modes. Data is available through the serial DDR LVDS or parallel CMOS interface and configured via SPI. An integrated digital down-converter is included in the MCP37DX1-200 family making it ideal for communications applications. The 12-bit families include an integrated noise-shaping requantizer, which enables users to lower the noise within a given band of interest for improved accuracy and performance. These families are targeted for applications in the communications markets such as base stations, test equipment, and IF receivers, among others.

adcRead full story!

 

The post Microchip announces new 16-bit A/D converters with 200Msps sampling rate appeared first on Embedded Lab.

Viewing all 713 articles
Browse latest View live