The Atmega328P is going too much fast

I am using atmega328P microcontroller for my project but the problem is sometimes the controller goes too much fast (looks like speed x10 or more). The problem occurs sometime not everytime and when the problem occurs we turn off board and then again turn on the problem is solved. Like we have default value of 30 when machine starts and the maximum it goes is 150. so we only hold the up button the value is changing but sometimes when value is going up it automatically starts to go up very fast, also the buzzer becomes fast and all other operations which is to be performed by controller becomes very fast which indicates the controller is going fast.
It sometimes comes 1 time in 15 and sometimes 5 times in 10.
The second problem which sometimes occurs is the controller becomes hang and same turning off the board and turning it ON again solves the problem.

The circuit which i am using is given below:

The PCB board design is shown below:

The other problem which i face is i dont have oscilloscope to check the signal quality.
So the possible causes which i think are:

  1. Problem in Crystal
  2. Poor Board Design

Also in arduino board they have used 1M ohm resistor in parallel with crystal. What is the purpose of that resistor as my board does not have.

  1. Your code can be a tremendous help for those that want to help.
  2. A proper schematic will also be useful.
  3. A functional description will also make life easier.
3 Likes

C11 and C12 in figure are marked as 22uF but actually they are 15pF.

This is the schematic and the function of board is it is automatic tyre inflation machine which is used to fill or drain air from tyre.

For code it is too much long above 2000+ lines so i cannot post it but the libaries which i am using is LedControl.h and EEPROM.h
buttons used as active high(means when controller pin is high then controller reads it)
simple analogread for pressure sensors with averaging samples of 50 readings
and display code for displaying values.

Of course you can. You can split it over a few posts (make sure you don't miss something) or zip and attach it.

Is that the correct value for the xtal you are using?

Your 328P symbol seem to be wrong, the 328 has two ground pins.

How do you program the 328?

Hi, @abd42

Is there a reason you didn't just put some headers on your PCB and plug in an already setup controller, like a Nano?
It would have saved a lot of work and possibly this problem.

Tom.... :smiley: :+1: :coffee: :australia:

I will add to that

  • Poor circuit design
  • Poor software design
2 Likes

2000 lines of code, to say nothing of the libraries, seems a lot to accomplish what you have described

Are you sure that the code is not normally running slower than expected, perhaps because blocking code, and that what you regard as speeding up is, in fact, it running at normal speed ?

Please post your code

1 Like

The microcontroller is Atmega328P and the crystal is 16 MHz.

What is the load capacitance specification for that crystal?

The taces to the crystal and caps should be as short as possible.
That is not the case here.
Maybe you can improvise and solder the caps on the other side of the board...
Or maybe have a 8MHz crystal to run at 8 MHz...

I think you should first consider software issues...
As your problem seems related to pressing the speed button, there seems little reason to think that the oscillation circuit is unstable...

I would also think a software error is highly possible. The use of String variables would likely eventually consume all available ram and overwrite something that is caused what appears to be a speed change. Writing outside the bounds of an array, or running past the minimum/maximum value that can be stored in a numeric (byte, int, etc) variable are other possibilities.

#include <EEPROM.h>
#include "SPI.h"
#include <LedControl.h>
#include "elapsedMillis.h"
#define MAX_DEVICES 1

// Pins for MAX7219 connections
#define DATA_IN   8  // Pin for DATA IN
#define LOAD      7  // Pin for LOAD (CS)
#define CLOCK     6  // Pin for CLOCK (CLK)

// Create an LedControl object
LedControl lc = LedControl(DATA_IN, CLOCK, LOAD, MAX_DEVICES);

int m_sec;

byte pres_sensor = A3;
int sensorvalue=0;
float pres_target0,pres_target=30.0, pres_ini_multipleS =1;
boolean pres_filling,pres_draining, name_disp , pres_complete =0, Mode_init =0 ,name_erase=0, Font, pros_start =0;
uint8_t blink_counter=0, pres_est_reset =200, stay_counter=0, name_check =0;
byte tyre_counter =0, reevaluation_inf, name_change = 0;
String retrievedString,  retrievedString2;
char rx_byte = 0;
String rx_str;
int tar_pres_up, tar_pres_down, MenuCancel, refill;
byte air_supply=3;
byte buzzer= 4;
byte air_drain=5;
float total =0, average=0;
int numReadings = 0;
bool isPOfShown = false;
bool PDPI = false;
bool TIIS = false;
bool ASSF = false;
bool ADDF = false;

byte P_Ofst = EEPROM.read(50);
byte PDPipe = EEPROM.read(60);
byte Ti_S = EEPROM.read(70);
//byte Ti_D = EEPROM.read(80);
byte AS_F = EEPROM.read(90);
byte AD_F = EEPROM.read(100);
byte E_Font = EEPROM.read(120);
byte S_Vol = EEPROM.read(130);
byte D_Vol = EEPROM.read(140);
byte R_time = EEPROM.read(150);
byte name_disp_ram=1;
int refill_time = R_time *1000;
int tyre_c62500 = EEPROM.read(169);
int tyre_c250 = EEPROM.read(170);
int tyre_c1 = EEPROM.read(171);
uint8_t Menu = 0;
float Pressure_offset = P_Ofst -100;
double  t_tyre_count;
unsigned long time_initial_S = 0;
unsigned long time_initial_D = 0;
byte air_supply_factor = AS_F;                                    // Initial Time Determination Factor
byte air_drain_factor = AD_F;
byte time_lapse_S = Ti_S;                                        // Initial lapse to counter small pressure difference
byte t_settling = 150;
byte t_d = 150;
long int est_inf_time=0, est_def_time=0, pres_inf_est0 =0, pres_inf_est1 =0, pres_def_est0 =0, pres_def_est1 =0;
float pres_check,pres_settling, pres_tyre_stable_ref, pres_val, pres_psi, pres_psi0, pres_bar,  pres_pas, pres_volt,pres_tyre_diff, pres_inf_diff_ini, pres_def_diff_ini, pres_tyre_cur, pres_fill_ini0, pres_fill_ini1, pres_fill_ini2, pres_drain_ini0, pres_drain_ini1, pres_drain_ini2, pres_tyre_diff1=0;
String v1,d1;
byte i=0;
byte mno=0,num_offset=15;
float psi[15],pres_offset=0;

void setup()
{
Serial.begin(115200);
analogReference(EXTERNAL);
lc.shutdown(0, false);    // Wake up display
lc.setIntensity(0, 8);    // Set brightness (0-15)
lc.clearDisplay(0);      // Clear Display
lc.setDigit(0, 0, 8 , true);
lc.setDigit(0, 1, 8 , true);
lc.setDigit(0, 2, 8 , true);
lc.setDigit(0, 3, 8 , true);
delay(100);
lc.clearDisplay(0);
lc.setRow(0, 0, B01001110);
lc.setRow(0, 1, B11001111);
lc.setDigit(0, 2, 5 , false);
delay(1000);
Serial.println(readStringFromEEPROM(175));
retrievedString = readStringFromEEPROM(230);
Serial.println("NEW SOFTWARE");
Serial.println("Welcome : Enter Security Code...?");
Serial.println(pres_sensor);
pinMode(11,OUTPUT);
pinMode(13,OUTPUT);
pinMode(pres_sensor, INPUT);
pinMode(air_supply, OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(air_drain, OUTPUT);
digitalWrite(buzzer, HIGH);
delay_f(500);
lc.clearDisplay(0);
analogWrite(air_supply, 0);
analogWrite(air_drain, 0);
digitalWrite(11, LOW);
digitalWrite(13, LOW);

if(P_Ofst < 79 || P_Ofst > 121){
EEPROM.write(50,100);
delay_f(10);
P_Ofst = EEPROM.read(50);
Pressure_offset = P_Ofst -100;}

delay(100);
t_tyre_count = ((62500EEPROM.read(169)) + (250EEPROM.read(170)) + EEPROM.read(171));

if (tyre_c250 >= 132)
t_tyre_count = 65536 + t_tyre_count;
t_tyre_count /=4;
Serial.print("t_tyre_count : ");
Serial.println(t_tyre_count);
for(i=0;i<num_offset;i++)
psi[i] = 0;

}

void pres_deci(float pressure, float pressure0){
........................Used to show value
}

void showError() {
for (int i = 0; i < 5; i++) {  // Blink 3 times
lc.setChar(0, 0, 'E', false);
lc.setRow(0, 1, B00000001);
delay(500);
lc.clearDisplay(0);         // Clear the display
delay(500);
}
pres_deci(pres_target,pres_target0);  // Return to showing the current counter value
}

void showvalue(int valu){
lc.clearDisplay(0);
for (int i = 2; i >= 0; i--) {  // Adjust for 4 digits (starting from the leftmost digit)
int digit = valu % 10;          // Extract least significant digit
lc.setDigit(0, i, digit, false); // Display digit without decimal point
valu /= 10;                     // Shift to next digit
}
}

void pres_sens_read(){
pres_volt = 5.0MovAvg1(pres_sensor)/1023;
pres_psi = (40*pres_volt) - 20;
}

void pres_stabilize(){    // 500 bytes memory
.................
}

void pres_meet_check(){
............................
}

void delay_f(int del){                //600 bytes memory
delay(del);
}

void BDAMP(){
digitalWrite(buzzer, HIGH);     //buzzer
delay(15);
digitalWrite(buzzer, LOW);
}
void solenoid_operation_S(byte solenoid_type, unsigned int on_time1){
......................
}

void solenoid_operation_D(byte solenoid_type, unsigned int on_time2){
..................
}

void writeStringToEEPROM(int addrOffset, const String &strToWrite)
{
................
}

void Button_Read(){

tar_pres_up     =   digitalRead(A1);

tar_pres_down   =   digitalRead(A0);
MenuCancel      =   digitalRead(10);
refill          =   digitalRead(12);
pres_sens_read();
}

void delay_name(int del){                //600 bytes memory
m_sec =0;
delay(del);
}

void Buzzer(){
digitalWrite(buzzer, HIGH);     //buzzer
delay_f(40);
digitalWrite(buzzer, LOW);     //buzzer
delay_f(40);}

void  loop() {

Serial.print(pres_psi);
Serial.print("    ");
Serial.println(pres_offset);
digitalWrite(buzzer, LOW);     //b uzzer
analogWrite(air_supply, 0);
analogWrite(air_drain, 0);
digitalWrite(11,LOW);
digitalWrite(13,LOW);
pres_sens_read();
if(abs(pres_psi) > (0.3 + (Pressure_offset/10)))
psi[num_offset] = pres_psi + pres_offset  - (Pressure_offset/10);
for(i=0;i<(num_offset);i++){
psi[i] = psi[i+1];
Serial.print(psi[i]);
}
Serial.println("    ");
pres_offset = psi[0];

if ( Mode_init ==0 ){
Button_Read();
work_mode:
pres_deci(pres_target,pres_target0);
pres_target0 = pres_target;

if( tar_pres_up == HIGH && pres_target <= 144){                      // REMOTE or BUTTON COMMANDS PLUS PRESSURE LIMITS CHECK
pres_est_reset=0;
pres_target++;
pres_deci(pres_target,pres_target0);pres_target0 = pres_target;
Buzzer();
delay_f(700);
pres_up:
Button_Read();
if( tar_pres_up == HIGH && pres_target <= 144){
pres_target++;
pres_deci(pres_target,pres_target0);pres_target0 = pres_target;
Buzzer();
goto pres_up;}
}

else if( tar_pres_down  == HIGH && pres_target >17){                  // REMOTE or BUTTON COMMANDS PLUS PRESSURE LIMITS CHECK
pres_est_reset =0;
pres_target--;
pres_deci(pres_target,pres_target0);pres_target0 = pres_target;
Buzzer();
delay_f(700);
pres_down:
Button_Read();
if( tar_pres_down == HIGH  && pres_target >17){
pres_target--;
pres_deci(pres_target,pres_target0);pres_target0 = pres_target;
Buzzer();
goto pres_down;}
}
if ((MenuCancel == HIGH) && (refill == LOW) && (pres_psi < 5) ) {
pres_target=30.0;
pres_ini_multipleS =1;
pres_inf_est0=0;
pres_inf_est1=0;
pres_def_est0=0;
pres_def_est1=0;
pres_est_reset =253;
tyre_counter =0;
pres_deci(pres_target,pres_target0);
delay(1000);
Button_Read();
if ((MenuCancel == HIGH) && (refill == HIGH) && (pres_psi < 5)) {
delay_f(2000);
lc.clearDisplay(0);
Menu =20;
Mode_init=1;
}}

if (refill == HIGH && MenuCancel == LOW  && Mode_init==0) {
delay(t_d);
Button_Read();
if (refill == HIGH && MenuCancel == LOW) {
lc.clearDisplay(0);
lc.setChar(0, 0, 'F', false);

lc.setDigit(0, 1, 1, false);
// lc.setChar(0, 2, 'L', false);
lc.setChar(0, 2, 'L', false);
Buzzer();
solenoid_operation_S(air_supply, refill_time);
if(pres_psi < 10)
solenoid_operation_S(air_supply, 2*refill_time);
lc.clearDisplay(0);

while (pres_psi < 5){
digitalWrite(buzzer, HIGH);     //buzzer
digitalWrite(11,LOW);

digitalWrite(13,LOW);
showError();
Button_Read();
if (tar_pres_up == HIGH || tar_pres_down == HIGH || MenuCancel == HIGH || refill == HIGH){
digitalWrite(buzzer, LOW);    //buzzer
lc.clearDisplay(0);
goto work_mode;}
}}
lc.clearDisplay(0);

pres_sens_read();

pres_tyre_diff = pres_target - pres_psi;

while((pres_tyre_diff > (pres_target/3))){
pres_deci(pres_psi,pres_psi0);
time_initial_S = 2.5*pres_target*pres_tyre_diff*0.5*air_supply_factor;  //Basic Inflate Check
solenoid_operation_S(air_supply, time_initial_S);
pres_tyre_diff = pres_target - pres_psi;
pres_deci(pres_psi,pres_psi0);
}
time_initial_S=0;
}

if ((MenuCancel == HIGH) && (pres_psi < 10) ) {
delay(200);
Button_Read();
if ((MenuCancel == HIGH) && (tar_pres_down  == HIGH ) && (pres_psi < 10)) {
lc.clearDisplay(0);
pres_sens_read();
showvalue(pres_psi);
delay(2000);
showvalue(pres_offset);
delay(2500);
lc.clearDisplay(0);
lc.setChar(0, 0, 'H', false);

lc.setDigit(0, 1, 0 , false);
lc.setChar(0, 2, 'L', false);
lc.setChar(0, 3, 'D', false);
delay(3000);
lc.clearDisplay(0);
}
}

if ((MenuCancel == HIGH) && (pres_psi < 10) ) {
delay(200);
Button_Read();
if ((MenuCancel == HIGH) && (tar_pres_up  == HIGH ) && (pres_psi < 10)) {
lc.clearDisplay(0);
lc.clearDisplay(0);
lc.setRow(0,0,B01001110);
lc.setDigit(0,1,0,false);
lc.setRow(0,2,B00111110);
delay(1000);
t_tyre_count = ((62500*EEPROM.read(169)) + (250*EEPROM.read(170)) + EEPROM.read(171));
if (tyre_c250 >= 132){
t_tyre_count = 65536 + t_tyre_count;}

t_tyre_count /=4;
showvalue(t_tyre_count);
delay(4000);
lc.clearDisplay(0);

}}

if ( blink_counter > 10){
blink_counter =0;}
blink_counter++;
delay(1);
}

if (pres_est_reset > 250 || tyre_counter ==4 ){
pres_ini_multipleS =1;
pres_est_reset =253;
tyre_counter =0;
}
pres_est_reset++;
delay_name(50);

if (pres_psi > 5 && MenuCancel == LOW && (Mode_init == 0) ){
digitalWrite(buzzer, HIGH);     //buzzer
mno= PDPipe0.5pres_target;
solenoid_operation_S(air_supply, mno);
digitalWrite(buzzer, LOW);     //buzzer
delay(10);
pres_meet_check();
}
while (pres_psi > 5 && (Mode_init == 0)){ //                                             Main FILLING DRAINING LOOP

.............(Program do not enter this loop because the problem occurs outside that loop when pres_psi<5)

pres_meet_check();

while ( pres_psi > pres_target)       //Drain While Loop
{
.............Mathematical Calculations and Solenoid Coil ON/OFF (Confidential)
}

while ( pres_psi > 5 && pres_psi <= pres_target)      //Filling While Loop
{
………….Mathematical Calculations and Solenoid Coil ON/OFF (Confidential)
}
}

if (pres_complete == 1){
lc.clearDisplay(0);
while (pres_complete == 1){
digitalWrite(buzzer, HIGH);     //buzzer
digitalWrite(11,LOW);
digitalWrite(13,LOW);
showError();
Button_Read();
if (tar_pres_up == HIGH || tar_pres_down == HIGH || MenuCancel == HIGH || refill == HIGH)
pres_complete = 0;
}
digitalWrite(buzzer, LOW);     //buzzer
delay(1000);
lc.clearDisplay(0);
}

if ( (Menu ==20) && (Mode_init == 1)){
if (!PDPI) {
lc.setChar(0, 0, 'P', false);
lc.setChar(0, 1, 'D', true);
lc.setChar(0, 2, 'P', false);
delay(1000);
PDPI = true;  // Set the flag so it doesn't show again
}
Button_Read();
d1 = String(PDPipe,DEC);  //Value check
showvalue(PDPipe);
delay_f(20);
delay_f(10);
if ( tar_pres_up == HIGH && PDPipe < 100){
PDPipe++;
EEPROM.write(60,PDPipe);
}

else if ( tar_pres_down == HIGH && PDPipe > 0){
PDPipe--;
EEPROM.write(60,PDPipe);
}

else if(MenuCancel == HIGH){
delay(1000);
Button_Read();
if(MenuCancel == HIGH){
Menu=3;
lc.clearDisplay(0); }
}

}

……………….Setting more parameters

else if ( (Menu ==8) && (Mode_init == 1)){
if(MenuCancel == HIGH){
delay(1000);
Button_Read();
if(MenuCancel == HIGH){
Menu=0;
Mode_init=0;
lc.clearDisplay(0);
isPOfShown = false;
PDPI = false;
TIIS = false;
ASSF = false;
ADDF = false;
}
}}

Button_Read();
if ( (refill == HIGH) && (Mode_init == 1)) {
Menu=0;
Mode_init=0;
isPOfShown = false;
PDPI = false;
TIIS = false;
ASSF = false;
ADDF = false;
lc.clearDisplay(0);
delay(500);

}
}

float MovAvg1(int inputPin)
{
total =0.0;
numReadings = 50.0;
for (int i=0; i<numReadings; i++){
delay(1);
total = total + analogRead(inputPin);
}
average = total / (1.0*numReadings);
Serial.println(average);
return average;
}

Thank you for posting your sketch but please edit your post, select all of the code
and click on the code tags icon ( < / > ) above the post editor to add code tags then save the revised post

If you want to be even more helpful then in my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

See How to get the best out of this forum

Unable to do it here with the code you posted, so you will need to tell us, how much free ram does the compiler show when you compile the sketch? You are using some very large String variables. It would also help if you used the F() macro for text literals.

Compiling your sketch in #13 creates a lot of errors, even when installing the used libraries. I think you copied it wrong.
Please post it again, following the instructions from @UKHeliBob in #14.

I think that some * were dropped. I know that that can easily happen when using de WYSIWIG editor on the forum.

And there are lines with ..... where OP tried to add indications of issues or possibly removed a long block of code. The latter however does not help us to help OP.

E.g. this

.............Mathematical Calculations and Solenoid Coil ON/OFF (Confidential)

And without that I doubt we can help.

Seeing Confidential in your code means that we can't really help. That code might eat away your memory but we can't judge.

If you need help you will have to provide full code. If you don't want to release code to the public but are prepared to pay I suggest that you flag your post and ask it to be moved to Jobs and Paid Consultancy - Arduino Forum; you can ask helpers there to sign an NDA.

You should look at the eeprom put() and get() functions, as well as the idea of putting all the variables store in eeprom into a struct, that could greatly simplify the code.

Eliminate the use of String and your problem will very likely go away.

Uploading Blink and seeing it run at the given rate (or not) should establish whether there's any crystal-clock troubles.

6 Likes