NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Need help with ADC on atmega168

September 24, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

I need some serious help. I'm using an atmega168 to create a parking lot management tool. It has a flexforce sensor and photoelectric sensor (similar to a garage door sensor) as a way of seeing when a car enters or exits the lot. I'm using the ADC pins since the sensors give out a strictly analog signal and have set up my code as such so that it displays out to an LCD, which I will also be connecting wireless with a pair of Xbees. My code is as such: void adc_init() { ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); //Enable ADC and set 128 prescale }

int main(void)
{
   ADCSRA |= 1<<ADPS2;
   ADMUX |= 0<<REFS0 | 0<<REFS1;
   ADCSRA |= 1<<ADIE;      //enables the use of interrupts for the program
   ADCSRA |= 1<<ADEN;      //ADC enabled

   sei();

   ADCSRA |= 1<<ADSC;

    while(1)
   {
   }
}   
   ISR(ADC_vect)
   {
      uint8_t Entrance = ADCL;
      uint16_t Exit = ADCH<<8 | Entrance;

      lcd_init();
      FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);      //these functions are included in lcd.c and lcd.h to initialize the LCD
      lcd_home();

      uart_init();
      FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);         //these functions are in the UART include files and are used to send data from the uart to the lcd
      stdin = stdout = &uart_stream;

      int x = 0;

      switch (ADMUX)
      {
         case 0xC0:
                  ++x;   //increment the counter to show a vehicle passed
                  fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                  lcd_line_one();   //clears the other LCD rows so that the output is only on the first line of the LCD
                  PORTB |= (1<<PB0);
                  delay_ms(10);
                  PORTB &= ~(1<<PB0);
                  ADMUX = 0xC1;
                  break;

         case 0xC1:
                  --x;
                  fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                  lcd_line_one();
                  PORTB |= (1<<PB1);
                  delay_ms(10);
                  PORTD &= ~(1<<PD1);
                  ADMUX = 0xC0;
                  break;

         default:
                  //Do nothing
                  break;
      }

   ADCSRA |= 1<<ADSC;

   }

So I ran an Isis simulation using pot resisters as the two sensors, but I can't get anything to run and nothing is displaying on the LCD. What am I doing wrong?

September 24, 2012
by JimFrederickson
JimFrederickson's Avatar

The first thing...

Even if there is not a problem with setting up the ADC for Interrupt use this will likely never work properly...

You need to develop and understand in your mind a division between "Main Code" and "Interrupt Code"...

You really want your interrupt code to be extremely focused, and to ONLY do what is necessary. If you do too much in your interrupt code then you will run into a variety of issues.

The code you have here is setup so that all of the processing is taking place in the Interrupt Routine. While this is relatively easy to program it is not a good idea.

Your "While (1)" Loop in your main function needs to be the place there you perform most of your code functions and display data onto the LCD...

The "ADC Interrupt Routine" should ONLY be storing the result of the ADC, with minimal scaling/conversion/validation if necessary, into variables that are accessed and displayed within your "While (1)" Loop in your main function.

The variables that are used to store the results in/from the "ADC Interrupt Routine" need to be declared as "volatile".

What "volatile" means for this version of "C" is that optimization will not take place on the storage of the variables in the compiled machine code.

The result is that each time these variables are used in the code their values are always reread from memory.

If you don't declare the variables as "volatile" then in a short loop the variable use may be "optimized" by the compiler and be stored in a Register on the Microcontroller and the values in memory may be changed by the "ADC Interrupt Routine" but your "Main Code" will not see the change.

You need to understand that the "C Code" you are compiling is not really telling "the Compiler what to do" it is telling "the compiler what you want to have done"...

Two, potentially, different things.

Also, if you are using byte values you can read the variables directly in your "Main Code" without too much issue PROVIDING that you do not use the variables more than once to process a specific result.

What I NORMALLY do, since byte variables are usually not what I end up using is to use a "byte semaphore".

"semaphores", in programming, are fairly easy to understand. Basically they are flags that are used to synchronize access to variables from two different/usually independent sections of code. (Whether they are scalar variables or structures, or whatever...)

The simplest thing for you to do is to use the "values from the ADC Interrupt Routine" as your "semaphores"...

Basically...

1 - In the "ADC Interrupt Routine" check the value of the the ADC Result variable. If it is zero then write a new value otherwise don't do anything.

What this means is that the "Main Code" has not processed that result yet, so a new result is not necessary and may actually cause problems for your program as well. Since your "ADC Interrupt Routine" is running currently your "Main Code" is suspending and not doing anything so there will be not conflict.

2 - In the "Main Code" you move the "non-zero ADC Result variables" into "ADC Result variables used by the "Main Code".

3 - Then in the "Main Code" you can now zero all of the "ADC Result variables". This will let the "ADC Interrupt Routine" that new values can be saved.

4 - Process the "ADC Result variables in the "Main Code" however your want.

There are other things that would be a good idea to consider as well, which isn't probably necessary for this application but may be...

1 - Sometimes there can be "anomalous results" produced by the Microcontroller ADC Process. There are a few methods to combat this, pretty much all methods rely in storing more than one iteration of the results, or averaging several results over a period of time. (The anomalies can be caused by a large number of issue, bad solder joints, bad connector if the sensors are remote, vibration affect connections, voltage variations in the supply, even induced voltage sometimes. Likely there are more potential causes as well...)

i.e.

ADC returns 968 ADC returns 962 ADC returns 961 ADC returns 54 ADC returns 961

If you processed the 54 ADC Result then you would have issues in your program.

2 - you really only need to rewrite the LCD Display if there is a change in the value not every time your process your loop.

Hopefully that will help...

September 24, 2012
by JimFrederickson
JimFrederickson's Avatar

I did note that the program you have so far is a "relatively simple program", but your ultimate goals are going to require that you think about many of the issues I mentioned...

September 24, 2012
by pcbolt
pcbolt's Avatar

ram -

Try setting up your code like the "tempsensor" project in the Nerdkit guide. You can add your interrupt routine afterward if you need to, but for this project it won't really help all that much. Check both your inputs one at a time then start testing both using the ADMUX register to switch between the two. Keep most if not all your code inside the while(1) loop. Is this the same project as the one HERE? Thought you had that nailed down.

September 24, 2012
by pcbolt
pcbolt's Avatar

Whoops...sorry Jim. I must have been composing my response while you were posting yours.

September 25, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

@pcbolt -- yeah, this is the same project. Turns out the sensors we have don't play too well as digital signals and the use of the ADC was the only way to go. We have started looking at using the comparator rather than using the converter so that way we just measure against AVref rather than taking the voltages, converting them, and then seeing if they work. This has been an absolute nightmare in coding, as I stated in that other topic, for someone who has no previous AVR experience and a very vague understanding of how microcontrollers work in general.

September 25, 2012
by pcbolt
pcbolt's Avatar

Ram -

You could try using two MOSFET's and a couple of voltage divider circuits to act as a comparator (one for each input). I don't know what values your sensors operate at, but it would be interesting to build. You could use Circuit Lab to to test it. I know some of the EE guys on this board eat problems like this for lunch and could give you some advice.

September 25, 2012
by pcbolt
pcbolt's Avatar

Ram -

You could try using two MOSFET's and a couple of voltage divider circuits to act as a comparator (one for each input). I don't know what values your sensors operate at, but it would be interesting to build. You could use Circuit Lab to to test it. I know some of the EE guys on this board eat problems like this for lunch and could give you some advice. If you have model numbers for your sensors that would be a huge help.

September 25, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

pcbolt -- I don't know about using MOSFETs to do that. From what I've been looking on the datasheet, the built in comparator circuit might be enough to do what we need to do. The only thing is coding around the comparison. The pressure sensor we use is a FlexiForce A201 and the photoelectric is the SunX CX21. Hopefully that helps with thinking of how to wire them up and solving this problem.

September 26, 2012
by Ralphxyz
Ralphxyz's Avatar

The FlexiForce Sensors are cool! The price is a little to steep for me but I can picture all sorts of ways to use them.

ram_engineerin_2012 what are you doing with them?

I have been looking at Instructables for instructions on building my own flex sensor.

The photoelectric sensor certainly looks like a tough one.

Ralph

September 26, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

Ralph --

The pressure sensors, in conjunction with the photoelectric sensors, are used to show that a car has entered the lot and increments the total for the number of cars in the current parking lot. For us, so long as the pressure is adequate enough to pass the voltage through the flex sensor and trip the light beam emitted from the photoelectric sensor, it should count as an entrance and/or exit. The problem we have is that since all the signals are now analog, we cannot use the previous setup we had before. We now must use the ADC to get a logical 1 so that way our if statements or switch statements can actually work. The sensors are set up in series so that way they act as a voltage adder and pass 5V to the ADC, since we use Vcc as AVref. The thing we are looking at now though, is that we are not getting a full 5V out from the adder, so we are thinking of using the comparator instead. Any thoughts?

September 26, 2012
by pcbolt
pcbolt's Avatar

Ram -

Here is a simple circuit using a MOSFET (2N7000 included with NK)

Mosfet Switch

Your FlexiForce sensor (without the OpAmp) should be substituted for resistor R2. This schematic with R2 equaling 100k ohm represents the sensor with a load on it. In this state the voltage on the MOSFET gate is enough to start the conduction through the transistor to ground. The voltage of "OUT_TO_MCU" is nearly 0. When no load is on the sensor, R2 will be above 5M ohm and the gate voltage won't be high enough to let the MOSFET conduct, therefore the "OUT_TO_MCU" will be 5 volts. What's nice about the ATmega168 is the internal pullup resistor can replace R3 in the circuit above. If enabled, you can remove the wire from the top of R2 and get rid of resistor R3. You may need to add a 100k pot between R1 and ground, but you can experiment with that.

As for your light sensor, you should test it to see what "sensor out" pin voltage is when the beam is on and when it is interrupted. A simple voltage divider (like R1 and R2 above) should get you to 5v.

October 20, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

So here's an update on the project and a whole new problem:

Our circuits have been fully integrated to where everything is powered by a power supply that we made. Our LCD was giving problems but we managed to get it working. Now our problem is that we can't at all see our program. I have tried old programs and new ones and still nothing. Here is our original code:

/*
 * Senior_Redux.c
 *
 * Created: 3/30/2012 12:23:08 PM
 *  Author: ghost_117
 *
 */

#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>      //standard included to make sure things are running smoothly
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\lcd.c"        //used the included files that came with our micro kit
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\lcd.h"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\delay.c"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\delay.h"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\uart.c"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\uart.h"

int main(void)
{
    lcd_init();
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);     //these functions are included in lcd.c and lcd.h to initialize the LCD
    lcd_home();

    uart_init();
    FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);           //these functions are in the UART include files and are used to send data from the uart to the lcd
    stdin = stdout = &uart_stream;

    unsigned char i;        //mostly to have the pins turn on and off
    int x = 0;              //our variable to count with
    uint8_t pb0_state = 0, pb1_state = 0;       //these variables are used to cycle a button press
    TCCR1B = 0x05;      //this register is altered so the internal clock is scaled by 1024
    DDRB = 0x00;        //used to set port B as input
    DDRC = 0x13;        //sets certain pins on port c as output

    PORTC = 0x00;       //just initialize the port

    while(1)
    {

      //i = PINB;           //the next two lines flash the LED on the corresponding ports

      //PORTC = i;

        if(x<=0){

                fprintf_P(&lcd_stream, PSTR("Lot is empty\n"), x);
                lcd_line_one();
                if (PINB & (1<<PB0)){       // is button down
                 if (pb0_state == 0){      // was button up before - if not do nothing
                                      ++x;  //increment the counter to show a vehicle passed
                                      fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                      lcd_line_one();   //clears the other LCD rows so that the output is only on the first line of the LCD
                                      pb0_state = 1;          // set button state to down
                                      PORTC |= (1<<PC0);
                                      delay_ms(10);
                                      PORTC &= ~(1<<PC0);
                                    }
                                }
                    else {                      // button is up
                          pb0_state = 0;            // reset button state to up
                         }

      //same as the previous block, but decrements instead
            if (PINB & (1<<PB1)){       // is button down
                 if (pb1_state == 0){      // was button up before - if not do nothing
                                      --x;
                                      fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                      lcd_line_one();
                                      pb1_state = 1;          // set button state to down
                                      PORTC |= (1<<PC1);
                                      delay_ms(10);
                                      PORTC &= ~(1<<PC1);
                                    }
                                }
                    else {                      // button is up
                          pb1_state = 0;            // reset button state to up

                         }              
                }

        else if(x<12){

            if (PINB & (1<<PB0)){       // is button down
                 if (pb0_state == 0){      // was button up before - if not do nothing
                                      ++x;  //increment the counter to show a vehicle passed
                                      fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                      lcd_line_one();   //clears the other LCD rows so that the output is only on the first line of the LCD
                                      pb0_state = 1;          // set button state to down
                                      PORTC |= (1<<PC0);
                                      delay_ms(10);
                                      PORTC &= ~(1<<PC0);
                                    }
                                }
                    else {                      // button is up
                          pb0_state = 0;            // reset button state to up
                         }

      //same as the previous block, but decrements instead
            if (PINB & (1<<PB1)){       // is button down
                 if (pb1_state == 0){      // was button up before - if not do nothing
                                      --x;
                                      fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                      lcd_line_one();
                                      pb1_state = 1;          // set button state to down
                                      PORTC |= (1<<PC1);
                                      delay_ms(10);
                                      PORTC &= ~(1<<PC1);
                                    }
                                }
                    else {                      // button is up
                          pb1_state = 0;            // reset button state to up
                         }
      }

     else if (x>=12){
            fprintf_P(&lcd_stream, PSTR("Lot is full!\n"));
            lcd_line_one();
            PORTC |= (1<<PC0);
            delay_ms(10);
            PORTC &= ~(1<<PC0);
            delay_ms(10);

            PORTC |= (1<<PC1);
            delay_ms(10);
            PORTC &= ~(1<<PC1);
            delay_ms(10);

            if (PINB & (1<<PB0)){       // is button down
                 if (pb0_state == 0){      // was button up before - if not do nothing
                                      ++x;  //increment the counter to show a vehicle passed
                                      fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                      lcd_line_one();   //clears the other LCD rows so that the output is only on the first line of the LCD
                                      pb0_state = 1;          // set button state to down
                                      PORTC |= (1<<PC0);
                                      delay_ms(10);
                                      PORTC &= ~(1<<PC0);
                                    }
                                }
                    else {                      // button is up
                          pb0_state = 0;            // reset button state to up
                         }

      //same as the previous block, but decrements instead
            if (PINB & (1<<PB1)){       // is button down
                 if (pb1_state == 0){      // was button up before - if not do nothing
                                      --x;
                                      fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                      lcd_line_one();
                                      pb1_state = 1;          // set button state to down
                                      PORTC |= (1<<PC1);
                                      delay_ms(10);
                                      PORTC &= ~(1<<PC1);
                                    }
                                }
                    else {                      // button is up
                          pb1_state = 0;            // reset button state to up
                         }
      }      
    }
    return 1;
}

And this is the new one:

/*
 * AVRGCC1.c
 *
 * Created: 9/26/2012 6:11:05 PM
 *  Author: ghost_117
 */

#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>      //standard included to make sure things are running smoothly
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "lcd.c"        //used the included files that came with our micro kit
#include "lcd.h"
#include "delay.c"
#include "delay.h"
#include "uart.c"
#include "uart.h"

int main(void)
{
    ADCSRA |= 1<<ADPS2;
    ADMUX |= 0<<REFS0 | 0<<REFS1;
    ADCSRA |= 1<<ADEN;      //ADC enabled

    lcd_init();
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);     //these functions are included in lcd.c and lcd.h to initialize the LCD
    lcd_home();

    uart_init();
    FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);           //these functions are in the UART include files and are used to send data from the uart to the lcd
    stdin = stdout = &uart_stream;

    int x = 0;              //our variable to count with
    //TCCR1B = 0x05;        //this register is altered so the internal clock is scaled by 1024
    DDRB = 0x13;        //sets certain pins on port c as output

    while(1)
    {

                fprintf_P(&lcd_stream, PSTR("Lot is empty\n"), x);
                lcd_line_one();

    start:

        if(x<=0){

                switch(ADMUX){

                        case 0xC0:
                                ++x;    //increment the counter to show a vehicle passed
                                fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                lcd_line_one(); //clears the other LCD rows so that the output is only on the first line of the LCD
                                PORTB |= (1<<PC0);
                                delay_ms(10);
                                PORTB &= ~(1<<PC0);
                                goto start;

                        case 0xC1:
                                --x;
                                fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                lcd_line_one();
                                PORTB |= (1<<PC1);
                                delay_ms(10);
                                PORTB &= ~(1<<PC1);
                                goto start;

                      }
        }

else if(x<12){

            switch(ADMUX){

                        case 0xC0:
                                ++x;    //increment the counter to show a vehicle passed
                                fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                lcd_line_one(); //clears the other LCD rows so that the output is only on the first line of the LCD
                                PORTB |= (1<<PC0);
                                delay_ms(10);
                                PORTB &= ~(1<<PC0);
                                goto start;

                        case 0xC1:
                                --x;
                                fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                lcd_line_one();
                                PORTB |= (1<<PC1);
                                delay_ms(10);
                                PORTB &= ~(1<<PC1);
                                goto start;

            }
}

     else if (x>=12){

                    fprintf_P(&lcd_stream, PSTR("Lot is full!\n"));
                    lcd_line_one();
                    PORTB |= (1<<PC0);
                    delay_ms(10);
                    PORTB &= ~(1<<PC0);
                    delay_ms(10);

                    PORTB |= (1<<PC1);
                    delay_ms(10);
                    PORTB &= ~(1<<PC1);
                    delay_ms(10);

                    switch(ADMUX){

                        case 0xC1:
                                --x;
                                fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                                lcd_line_one();
                                PORTB |= (1<<PC1);
                                delay_ms(10);
                                PORTB &= ~(1<<PC1);
                                goto start;
                    }                               
                }
    return 1;
        }
    }

Is there anything that we are doing wrong? I feel like something isn't right, but I just can't find it. Also, we are planning on installing XBEEs into our circuit and I don't know where or how to insert code for them. Any thoughts? I will also be including pics of our current circuit.

Power Supply Sensors and Amps

October 20, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

And here is the LCD and AVR

![LCD and AVR}(http://i.imgur.com/lZdTS.png)

October 20, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

Oops, here's the correction LCD and AVR

October 20, 2012
by JimFrederickson
JimFrederickson's Avatar

I have looked at what you posted several times.

Your statement of the current problem:
"Now our problem is that we can't at all see our program."

That doesn't make sense to me?
(Maybe it is just me?)

So what is the actual "problem now"?

October 21, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

Jim -- Our problem is that nothing is being output to our LCD. I have left the connection for the LCD as it was for the original circuit that Nerdkit says to use to get up and running. The only thing that comes out is two rows of faint black squares, similar to when you just plug in the LCD with no microcontroller.

October 22, 2012
by JimFrederickson
JimFrederickson's Avatar

In this situation...

The VERY FIRST THING I would do, without touching too much/anything of your circuit would be to reload the NerdKits Welcome Program.

Does that work?

If that doesn't work then you know that:

1 - Something is wrong with your MCU
2 - Something is wrong with your connections to the LCD
3 - Something is wrong with your LCD
4 - Something in your circuit is interfering with the MCU
(Which I would think is the least likely condition, but it still may exist...)

If that DOES WORK, well then you know it is something with your code.

October 22, 2012
by JimFrederickson
JimFrederickson's Avatar

It sounds as though the entire project you are working on is still on the breadboard...
(Maybe I have the wrong impression...)

For me, I REALLY hate redoing most things I have already done.
(Debugging circuits for instance...)

So to get around, at least one instance of this, I have my core that is soldered.

That way I don't have to worry, or concern myself, with the problem of loose breadboard connections, connections that have gotten pulled off, etc...

AVR-Protoboard

The base board I settled on was from Evil Mad Scientist.
(Actually I would purchase ALOT MORE from them if they had more stock...
Mostly though I use other sources for alot of what I purchase, but I really do like them as a company though.)

They are $3 apiece, or if you get 10 even a bit cheaper.
(you may find the $11 "Kit product" in their store, but there are also bareboards too.)

The quality does seem to be good as well.

Basically I set it up like the initial Nerdkits Circuit.

In the lower right is the Serial Programming Connector.

One thing you can't see is that the crystal in is a socket as well.

I used a Female Single Inline Header to get access to all of the I/O Pins.

AVR-Protosystem

My actual "Protosystem" has a connection to the LCD as well as to a 4x4 Keyboard.

I just use a ribbon cable, and stripped off each of the wires and soldered them to "single inline headers". Then I wound some heavy nylon sewing thread around it and epoxied it to give it some more strength. (The epoxy is the lighter grey color...)

At the top of the Protoboard, I did make a change and add a series of 4-Pin Female Headers so that I can have connections to the ADC inputs that I don't use along with power, ground, and a key-pin. (NOTE: That addition doesn't work as well with the ZIF socket since it takes up 2 of the rows necessary.)

There is some "black heat shrink" on the LCD Data Connection. That "black heat shrink" is for the backlight resister. (Normally, I don't have a POT for that, but sometimes I so as well.)

For me, doing it this way solves alot of debugging problems.

This way I KNOW that the core, the MCU portion, of ALL of my circuits is working well.

That way I ONLY have to debug/fault check the portion that is only on the breadboard.

In addition it allows me to have a "stockpile" of working cores, that I can interchange if I suspect some issue with one.

Your project seems pretty involved, and I think you may benefit from this approach as well, so I thought I would mention it.
(Regardless of what board you choose to ultimately use...)

Post a Reply

Please log in to post a reply.

Did you know that you can control 120 LEDs with just 17 microcontroller pins? Learn more...