Code uploads successfully on Atmega328p-au tqfp based pcb but does not work.

Hello
I have designed an arduino 328p tqfp package based pcb.
It also has on board 12V lithium ion battery protection and input from it to IC.
I checked all the voltages and found nothing wrong.
I am trying to run a 12V fan based application with switch and led interfaces.
The code works perfectly on the arduino uno.
Have attached the schematic and the code.
Can anyone suggest what am I missing here?

include.pdf (106 KB)

AtmegaP101.pdf (23.7 KB)

Please follow the advice on posting a programming question given in Read this before posting a programming question

In particular note the advice to Auto format code in the IDE and to use code tags when posting code here as it prevents some combinations of characters in code being interpreted as HTML commands such as italics, bold or a smiley character, all of which render the code useless

Ok noted. But, I do not have a programming related issue. The code is working fine on the proven arduino uno and as I bootload it on my pcb which is based on Atmega328p (tqfp package), it uploads successfully, but the issue is that the pcb does not show any output as it shows on the arduino uno. Any suggestions?

Which bootloader does the chip have on it ?
How are you doing teh upload to the chip ?
Can you upload and run a simple "Hello World" sketch ?

I note that your code uses #defines such as

#define LED1 PD6

Is there are reason why you are doing this rather than using the normal Arduino pin numbers ?

Hi,
Welcome to the forum.

Please read the post at the start of any forum , entitled "How to use this Forum".
OR
http://forum.arduino.cc/index.php/topic,148850.0.html.
Then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Can you repost your attachments please.
The code can be posted as shown in the above reference.
The circuit would be better in jpg, to make it easier to read on most platforms.

Thanks.. Tom..... :slight_smile:

Show your code in your post, not in an attachment. And since your code works on an Uno but not on your 328thing, you have ruled out the bug being in your code. So don't use your code here. Write the simplest scetch which should run on a Uno and on your 328thing. Get that working. If it doesn't, the fault is in your 328thing. And it will be easier for someone to help you if you just use the simplest code.

I am using ICSP of arduino uno to bootload the code on my pcb. I tried using arduino pin numbers also, but it was not working on the pcb so I changed them. Some components are not yet soldered as they are yet to arrive, but they are all related to battery protection and cannot interfere the control side.
Here is the image of my pcb

and the code

//#include <Wire.h>
//#include <SPI.h>
#define sw PD5 //pin at push sw is connected
#define LED1 PD6
#define LED2 PD7 // led
#define LED3 PB0
#define LED4 PB1
#define fan PD4 //Fan

int lastButtonState = HIGH;   // the previous reading from the input pin
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
bool buttonState = HIGH; //saving state of the switch
byte tapCounter; //for saving no. of times the switch is pressed
int timediff; //for saving the time in between each press and release of the switch
bool flag1, flag2; //just two variables
long double presstime, releasetime; //for saving millis at press and millis at release
int a=0;

unsigned long i1=900000; unsigned long i2=1800000; unsigned long i3=3600000; unsigned long i4=7200000;
void setup() {
  Serial.begin(115200);
  pinMode(sw, INPUT_PULLUP); //setting pin 5 as input with internal pull up resistor
  pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED3, OUTPUT); pinMode(LED4, OUTPUT); pinMode(fan, OUTPUT);
}

void loop() {
  int reading = digitalRead(sw);
unsigned long time;
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;
      Serial.println("Button State:");
    }
  }
  //when switch is pressed
  if (buttonState == 0 && flag2 == 0)
  {
    presstime = millis(); //time from millis fn will save to presstime variable
    flag1 = 0;
    flag2 = 1;
    tapCounter++; //tap counter will increase by 1
    //delay(10); //for avoiding debouncing of the switch
  }
  //when sw is released
  if (buttonState == 1 && flag1 == 0)
  {
    releasetime = millis(); //time from millis fn will be saved to releasetime var
    flag1 = 1;
    flag2 = 0;

    timediff = releasetime - presstime; //here we find the time gap between press and release and stored to timediff var
    //Serial.println(timediff);
    //delay(10);
    }
    
  if ((millis() - presstime) > 400 && buttonState == 1) //wait for some time and if sw is in release position
  {
    time=millis();
    if (tapCounter == 1) //if tap counter is 1
    {  if (timediff <= 400) //if timediff is less than 400 then its a single tap
       {
        Serial.println("single tap");
         while((millis()-time)<i1)
          {
            nolight();
            digitalWrite(fan, HIGH);
            digitalWrite(LED1, HIGH); //fn to call when singletap
          }
       }
    }
    else if (tapCounter == 2) //if tapcounter is 2
    { if (timediff <= 400)  // if timediff is less than 400 then its just double tap
      {
        Serial.println("double tap");
         while((millis()-time)<i2)
         {
           nolight();
           digitalWrite(fan, HIGH);
          digitalWrite(LED2, HIGH); //fn to call when doubletap
         }
      }
    }
    else if (tapCounter == 3 ) //if tapcounter is 3 //then its triple tap
    {  Serial.println("triple tap");
       while((millis()-time)<i3)
       {
        nolight();
        digitalWrite(fan, HIGH);
        digitalWrite(LED3, HIGH); //fn to call when triple tap
       }
    }
    else if (tapCounter == 4) //if tapcounter is 4 then its 4 tap
    {  Serial.println("four tap");
       while((millis()-time)<i4)
      {
       nolight();
       digitalWrite(fan , HIGH);
       digitalWrite(LED4, HIGH);//fn to call when four tap
      }
    }
    nolight(); 
    tapCounter = 0;
  }
  lastButtonState = reading;
}
void nolight()
{
  digitalWrite(LED1, LOW);
  digitalWrite(LED2, LOW);
  digitalWrite(LED3, LOW);
  digitalWrite(LED4, LOW);
  digitalWrite(fan, LOW);
}

I also tried a simple blink code, but nothing on the output.

Just toi clarify: This exact code runs on your Uno?

#define sw PD5
.
.
.

void setup() {
  Serial.begin(115200);
  pinMode(sw, INPUT_PULLUP); //setting pin 5 as input with internal pull up resistor
.
.
.
}

Arduino convention requires pinMode(...) to use Arduino board pin numbers (e.g. 2, 3, 4, ...) and not processor pin names. Its possible in some cases that the pin name (e.g. PD5) happens to be the same number as the pin number on the board but it's not assured.

If you're going to use direct processor references like PD5 then you probably want to move away from Arduino-based pin and port functions like pinMode, digitalWrite etc to direct port manipulation.

Thank you @Blackfin
I did use processor pins as well as port pins in the code and tried running the led on pcb. But it did not work.
Is my schematic correct? Is this a hardware issue? Should I upload the Gerber files for reference?

PD6 & PD7 are analog input signals only, they cannot be used to drive LEDs.
#define LED1 PD6
#define LED2 PD7 // led

Suggest you jumper them over to some other unused pins. Uno/328P in DIP does not have those pins accessible.

You could have brought Rx, Tx, Gnd to a header and used that for serial access with an offboard USB/Serial adapter (FTDI Basic or similar), would have made life a little easier by allowing access to Serial.print() for debugging.

I only see 1 (one) 0.1uF cap for the three VCC, VCC, AVCC pins. Would have better to have one on each.

Maybe you can try some simple LED blinky code with direct port access to see if the processor is running:

const uint8_t pinLED1 = PORTD6;     //Uno pin '6'
const uint8_t pinLED2 = PORTD7;     //Uno pin '7'
const uint8_t pinLED3 = PORTB0;     //Uno pin '8'
const uint8_t pinLED4 = PORTB1;     //Uno pin '9'

#define portLED1    PORTD
#define portLED2    PORTD
#define portLED3    PORTB
#define portLED4    PORTB

uint32_t
    timeNow,
    timeLED;

void setup( void )
{
    //
    DDRD = (1<<pinLED1) | (1<<pinLED2);
    portLED1 |= (1<<pinLED1);
    portLED2 &= ~(1<<pinLED2);
    
    DDRB =  (1<<pinLED3) | (1<<pinLED4);
    portLED3 |= (1<<pinLED3);
    portLED4 &= ~(1<<pinLED4);
        
}//setup

void loop( void )
{
    timeNow = millis();
    if( (timeNow - timeLED) >= 250ul )
    {
        timeLED = timeNow;
        portLED1 ^= (1<<pinLED1);
        portLED2 ^= (1<<pinLED2);
        portLED3 ^= (1<<pinLED3);
        portLED4 ^= (1<<pinLED4);
        
    }//if
    
}//loop

Another advice - try to fuse Atmega for internal 8MHz oscillator. AVR is picky for crystal circuit layout.

AVR is not too picky about the crystal. Have ground plane underneath it on both sides of the board, and don't run any signals that switch levels a lot under it, and minimize near it.
Reset would be okay. SCK for the SPI bus would not.

Using the internal 8 MHz won't get you 16 MHz system clock speed, needed for 8 MHz SPI signals (altho that doesn't appear to be in use here).

Hi,
Can you post a jpg export of your PCB pattern please, so we can see component layout.

Do you have an oscilloscope?

Thanks.. Tom... :slight_smile:

I might be having a similar problem with a couple of my projects. They work fine on an UNO and Nano (but I have to change pin numbers) but when I try running them on a custom board its not working properly.

What is the best way to address a pin on the chip? I have been searching all morning and have seen quite a few methods, a lot say just use the Arduino pin number but that is not going to work.

Is it best to refer to them as:

define LED1 = D0

define SigIn = A0

and so on.

PS. I am trying to run it on an ATTiny3217.

Is there a pins_arduino.h file for that chip? You can determine referenence numbers from there.

Take a look here also for core files to add to the Arduino IDE for that chip.

Not that I could find.

I have seen a lot of stuff over on AVRFREAKS and it has totally confused me.

Surely if I refer to D3 on a 328 it would also refer to D3 on a 3217 or an 85. D3 should be D3 so long as you have selected the right chip in the compiler.

So you basically need a set of 'core files' to work with the board, that includes th software mapping between the physical pins and the name of the pin used in the software.
Take a look at the files being used at the link above.

I just had a bit of a play and something I was trying to do sort of work so getting there. I am actually using one of Spence's breakout boards.

Now I have broken something else, physical not code. Will get back to it soon.

So if I create my own board, which I am doing, I will need to use Spence's files or make my own pin file. Is this correct?

Use Spence Konde's core files, make your life a lot easier.