Sketch is not working with Nano perfectly like Mega2560

Hello All, :slight_smile:

I am using IR sensor for range measurement, and connected Motor and Valve with Arduino Mega for my project.

Function : At 'X' distance pump would turn on and 'X+Y' distance Valve would open in accordance with Rotary encoder (knob) position.

The sketch I have written is working perfectly with Mega but when I upload the same sketch on Nano, it stop working after some stages....I am using I2C communication with Sensor.. I don't know where is the problem...

Which things I should check in when uploading it to the Nano.

I would like to give you quick idea about the pins that I am using on Nano..

Analog pin : A0 to know the knob position (rotary encoder)
3V3 pin : to power the Sensor
A4 and A5: SDA and SCL respectively to the sensor
D4: pump LED to know that the pump is running
D6: Valve LEd to know that the Valve is open
D8: Pump pin to turn on/off the pump
D10: Vavle pin to open/close the Valve

to operate the pump and valve, I am connecting to their circuit using MOSFET.

GND pins: one GND pin to Sensor and another GND pin to 3 GND connections (LED circuit's Ground, Pump and Valve circuit's Ground and Rotary Encoder's Ground)

Can you please help me..

Thank you for going through my query in advance.

Regards,
Nisarg

Could you post the code please? (using code tags)

Unlike MEGA2560, the Nano doesn't really have a good 3.3V source. If you trace the circuit, you will find that 3.3V comes from the USB/TTL adapter. It is rather weak, maybe only able to supply 50mA or less depending on what USB/TTL adapter chip is used. Connect your MEGA2560 and try to power the sensors with it, while running code on Nano. All you need is to disconnect 3.3V from nano and connect to MEGA2560, then connect grounds of the two.

liudr:
All you need is to disconnect 3.3V from nano and connect to MEGA2560, then connect grounds of the two.

While this solution will work, if he has to use the MEGA for its 3.3V he might as well just use the MEGA for everything rather than using two arduinos. My guess is that OP wanted to switch away from using the MEGA to using just the nano.

It's just my hunch that the 3.3V supply was the culprit. If that is proven with the help of the MEGA2560, OP can get am1117-3.3 to supply the 3.3V.

Hi,

Thanks liudr and Michaelsm,

If I connect as per what liudr said, yes...it is working properly....The reason I want to use nano and not mega board is, I want to fit it in a housing in which only nano would fit....

The other problem I have noticed is, it happens when I connect pump and valve circuit to nano board (everything is connected to nano board only)..before that it worked properly...and with Mega board, everything works properly...So I don't understand why it only happens with the nano board and I have to use only nano board due to size constraint.

If I want to use only nano board, how can I use it..

Thanks again..

Hi again,

I got another problem... I noticed while using nano board, if I keep low baud rate (i.e.2400), it works perfectly...and if I keep higher baud rate (ie.9600 or higher),it doesn't give proper readings....
and to make the sensor work perfectly at lower baud rate (2400), I have to keep the serial monitor open..
If i connect nano with Mains supply, it also doesn't work...while this was not the case in Mega board.

What baud rate / Serail.begin do to microcontroller and how could I make the sensor work independent of Serial.begin/baud rate.

Thanks a lot..

The nano should work at up to 115200 baud rate. Unless yours is defective, it should work. Can you try the ASCII table example code at different rates with your nano? Don't connect to any of your current control circuit. If it works with higher baud rates, maybe your control circuit feeds back to your nano (say missing some flyback diode).

When you change your baud rate, did you change the IDE's serial monitor Baud also?

Your problem is still the 3V3 current delivery.

Maybe you could/should look into building a stand alone atmega board with decent 3V3 regulator added on it to solve your footprint issue.

These boards have a 3.3volt lineair regulator.
You could also use a bare 1117 3.3volt regulator with two caps "dead-bug" style if space is a problem.
Leo..

If I connect sensor with 3v3 of Mega and Common GnD, it still gives me faulty readings...
So after experimenting, I noticed following things...

in Nano board:
if baud rate 115200---with Serialmonitor open-- sensor works but gives faulty readings.
if baud rate is 2400---with Serialmonitor open-- sensor works pefectly....
Any baud rate 2400 or 115200 --- with Serialmonitor close -- Sensor stop working.. (I dont have to upload the code again, I just close the Serialmonitor window and sensor stops working)

I have tried ASCII code on nano...it gives me ASCII table at all the baud rates..

on Nano board:
LED blink command with delay...Without serialmonitor it works perfectly, with serialmonitor opened, it just turned on.

LED blink without delay ... Without Serialmonitor it works perfectly, with serial monitor it blinks but Slow....

and in my program, I am using total 110 ms delay which is the requirement from sensor to work and get the reading...
and I also use total 4 counters...and everytime I change the baud rate, counter timing also changes...

is there an issue with uC Timer!?..

Can you try another Nano?

I run rather complex sketches with Nanos and never had problems, but maybe your application drives it to its limits, although I doubt that.

nisargsolanki:
I am using I2C communication with Sensor.. I don't know where is the problem...

The other difference with a Mega and a Nano is that the Mega has 10k I2C pullup resistors.
The Nano does not have them.
So how long is the wiring between "the sensor" and the Nano.

Problems are usually resolved faster if posters include links to the parts, real pictures of the setup, and full code (inside code tags).
Leo..

Hello,

the wires' length is not more than 20cm...

Another problem I have just noticed: if I disable the Serial.begin from the code - sensor works but gives unexpected results...and to see it, I again need Serialmonitor..Do you think it is because of Serial port stack overflow.... (I have connected sensor to 3v3 nano pin)

I thought it would be too complicated since code is so long but ...
here is my code. :slight_smile:

#include <Wire.h>
#define VL6180X_ADDRESS 0x29     //  Device address of VL6180X  
#define getreading 1
#define wait 2
#define valveon  3
#define get_time 4
#define check_time 5
#define pumpoff 6

unsigned long targettime;
unsigned long waittime;
uint8_t next_stage = getreading;
int counter = 0;
int counter2 = 0;
int counter3=0;
int counter4=0;

int reading = 0;
int analogPin =A0;     // potentiometer wiper (middle terminal) connected to analog pin 3

int D4=4;
int D6=6;
int D8=8;
int D10=10;


void WriteByte (uint16_t subAddress, uint8_t data) {    //void WriteByte (uint16_t subAddress,uint8_t data)
  delay(10);
  Wire.beginTransmission(VL6180X_ADDRESS);     // I2C_I2CMasterSendStart(VL6180X_ADDRESS, I2C_I2C_WRITE_XFER_MODE);
  Wire.write((subAddress >> 8) & 0xFF);  //    I2C_MasterWriteByte((subAddress >> 8) & 0xFF);
  Wire.write(subAddress & 0xFF);           //  I2C_MasterWriteByte(subAddress  & 0xFF);
  Wire.write(data);                         //  I2C_MasterWriteByte(data);
  Wire.endTransmission();                  //  I2C_MasterSendStop();
  
}
//
uint16_t readByte (uint16_t subAddress) {

   
  Wire.beginTransmission(VL6180X_ADDRESS);
  Wire.write((subAddress >> 8) & 0xFF); // unit32 SCB_i2cMasterWriteByte (unit32 theByte)
  Wire.write(subAddress & 0xFF);
  Wire.endTransmission(false);
  delay(1);
  Wire.requestFrom(VL6180X_ADDRESS, 2);
//return read();

 reading = Wire.read();  // receive high byte (overwrites previous reading)
 //reading = reading << 8;    // shift high byte to be high 8 bits
 //reading |= Wire.read(); // receive low byte as lower 8 bit
 //return reading;

}


void setup () 
  {
    Serial.begin(2400);
    Wire.begin (); 
    pinMode (LED, OUTPUT);
    pinMode (D4, OUTPUT);
    pinMode (D6, OUTPUT);
    pinMode (D8, OUTPUT);
    pinMode (D10,OUTPUT);
    pinMode (A0,INPUT);

  
// initialize hardware registers etc.
 VL6180x_Init() ;

// WriteByte(0x0207, 0x01);
  }

  void VL6180x_Init() {
  
  delay(100);
      if (readByte(0x016) == 1) {

    WriteByte(0x0207, 0x01);
    WriteByte(0x0208, 0x01); 
    WriteByte(0x0096, 0x00); 
    WriteByte(0x0097, 0xfd); 
    WriteByte(0x00e3, 0x00); 
    WriteByte(0x00e4, 0x04); 
    WriteByte(0x00e5, 0x02); 
    WriteByte(0x00e6, 0x01); 
    WriteByte(0x00e7, 0x03); 
    WriteByte(0x00f5, 0x02); 
    WriteByte(0x00d9, 0x05); 
    WriteByte(0x00db, 0xce); 
    WriteByte(0x00dc, 0x03); 
    WriteByte(0x00dd, 0xf8); 
    WriteByte(0x009f, 0x00); 
    WriteByte(0x00a3, 0x3c); 
    WriteByte(0x00b7, 0x00); 
    WriteByte(0x00bb, 0x3c);
    WriteByte(0x00b2, 0x09); 
    WriteByte(0x00ca, 0x09); 
    WriteByte(0x0198, 0x01); 
    WriteByte(0x01b0, 0x17); 
    WriteByte(0x01ad, 0x00); 
    WriteByte(0x00ff, 0x05); 
    WriteByte(0x0100, 0x05); 
    WriteByte(0x0199, 0x05); 
    WriteByte(0x01a6, 0x1b); 
    WriteByte(0x01ac, 0x3e); 
    WriteByte(0x01a7, 0x1f); 
  WriteByte(0x0030, 0x00);
  // Recommended : Public registers - See data sheet for more detail
WriteByte(0x0011, 0x10); // Enables polling for ‘New Sample ready’
// // when measurement completes
WriteByte(0x010a, 0x30); // Set the averaging sample period
// // (compromise between lower noise and
// // increased execution time)
WriteByte(0x003f, 0x46); // Sets the light and dark gain (upper
// // nibble). Dark gain should not be
// // changed.
WriteByte(0x0031, 0xFF); // sets the # of range measurements after
// // which auto calibration of system is
// // performed
WriteByte(0x0040, 0x63); // Set ALS integration time to 100ms
WriteByte(0x002e, 0x01); // perform a single temperature calibration
// // of the ranging sensor 
//
WriteByte(0x001b, 0x09); // Set default ranging inter-measurement
// // period to 100ms
WriteByte(0x003e, 0x31); // Set default ALS inter-measurement period
// // to 500ms
WriteByte(0x0014, 0x24); // Configures interrupt on ‘New Sample
// // Ready threshold event’ 
WriteByte(0x001b, 0x09); // Set default ranging inter-measurement
 // period to 100ms
WriteByte(0x003e, 0x31); // Set default ALS inter-measurement period
 // to 500ms
WriteByte(0x0014, 0x24); // Configures interrupt on ‘New Sample
 // Ready threshold event’ 
    //}
    WriteByte(0x0016, 0x00);

  // end of setup
}
  }

void VL6180X_Poll_Range() {
 uint16_t tstatus;
 uint16_t range_status;
 
 // check the status
 tstatus = readByte(0x04f);
 range_status = tstatus & 0x07;
  //delay(10);


 // wait for new measurement ready status
 while (range_status != 0x04) {
// WriteByte(0x018, 0x01);
 delay(5);
 tstatus = readByte(0x04f);
 range_status = tstatus & 0x07;
 Serial.println("DEBUG: wait_for_ready");

 //Serial.println(tstatus);
 }
 
 }

it was the first portion of the code, since it was too long, I have to post it in 2 parts..
below is the rest of the code..

void loop() {
  
 static int rangeVal;     
  
  
  {
    // Start a range measurement in single shot mode//

   WriteByte(0x018, 0x01);


// poll for new sample ready ready //
 VL6180X_Poll_Range();
   // delay(50);  


Serial.print("Stage:");
Serial.println(next_stage);


switch (next_stage)
  {
    case getreading: // stage 1

         rangeVal = readByte(0x062);  //read the sensor value
         Serial.print(rangeVal);      //print the sensor value
         Serial.println("mm");        //print the mm
          
       if (rangeVal<=150 && rangeVal>50 ) {  //turn on the pump below 15 cm
          
          counter++;                   //starts counter at 0 and increase it by 1 step   // prevents falls triggering when something swipes below the sensor above some speed
          
          Serial.println(counter);
          Serial.print("millis() :");
          Serial.println(millis());
          //digitalWrite(42,HIGH);
          //digitalWrite(42,LOW);
          rangeVal = readByte(0x062);  //read the sensor value

          if(counter == 12)                // hand should remain in sensor area for counterx27 milliseconds
          {
          counter = 0;             //make the counter 0 
          digitalWrite(D4,HIGH);  //pump LED high                          
          digitalWrite(D8,HIGH);  //pump high
          Serial.println("pump is high");

          next_stage= valveon;}
       }
    else {
          counter = 0;           //makes the counter 0
          digitalWrite(D4,LOW);  //pump LED low
          digitalWrite(D8,LOW);  //pump low
          digitalWrite(D6,LOW);  //turn off valve LED
          digitalWrite(D10,LOW);  //turn off valve
          next_stage=getreading;}
           
    break;
    
case wait:    //stage 2

  digitalWrite(D4,LOW);  //pump LED low
  digitalWrite(D8,LOW);  //pump low

  counter2 = 0;          //makes the counter2 0
  rangeVal = readByte(0x062); 
  if (rangeVal <100){            // to spray even if pump is turned off
      next_stage= get_time;
    }     
  if (rangeVal > 180)
  {
    next_stage = getreading;        //if no hand, jumps to stage 1
  }
break;



 case valveon:  //stage 3
 
        rangeVal = readByte(0x062);      //read the value from sensor
        Serial.print(rangeVal);          //print the sensor value
        Serial.println("mm");            //print mm
              
      if (rangeVal<=100 ){ //&& rangeVal>=50 ) {            
      next_stage=get_time;            // to turn the valve on
      }

      else if (rangeVal<150 && rangeVal>100)
      {
        next_stage=valveon;              //will stay in same stage

        counter2++;                                      //turn off the pump after sometime if hand remain between 10 and 15cm
        Serial.println(counter2); 
        Serial.print("millis()stage3 :");
        Serial.println(millis());

        if (counter2 >= 15)           // to turn the pump off after counter2x42 milliseconds
        {
          next_stage = wait;           //jumps to stage 2
        }
      }
      else
      {
        next_stage=getreading;        //jumps to stage 1
      }
        break;
        
case get_time: //stage 4

            if (analogRead(A0)>700 ){                              //valve open for 250 milliseconds
              targettime=millis()+250;
              }
            else if (500<analogRead(A0) && analogRead(A0)<600 ){    //valve open for 500 milliseconds
              targettime=millis()+500;
              }
            else  if (300<analogRead(A0) && analogRead(A0)<400 ){    //valve open for 750 milliseconds
              targettime=millis()+750;
              }
            else if (200<analogRead(A0) && analogRead(A0)<300){      //valve open for 1000 milliseconds
              targettime=millis()+1000;
              }
             else if (100<analogRead(A0) && analogRead(A0)<200 ){     //valve open for 1250 milliseconds
              targettime=millis()+1250;
              }
              else if (analogRead(A0)<100 ){                         //valve open for 1500 milliseconds
              targettime=millis()+1500;
              } 
        next_stage=check_time;

             digitalWrite(D6,HIGH);                                 //valve high LED  
             digitalWrite(D10,HIGH);                                 //valve high
             

        break;
        
 case check_time: //stage 5

         rangeVal = readByte(0x062);  
         Serial.print (rangeVal);
       Serial.println (" mmstage5"  );                           // reads the sensor value

       if (millis() > targettime || rangeVal>=150 || rangeVal<50)  // set the condition when valve goes off
      
       
       {//Serial.print("millis 1:");                            //checks when valves goes off
        //Serial.println(millis());
 
        digitalWrite(D6,LOW);                             //valve LED off
        digitalWrite(D10,LOW);                             //Valve off
        
       
              next_stage=pumpoff;
       }
       break;
       
case pumpoff:                 //stage 6

      


rangeVal = readByte(0x062);   // measureas the sensor value
Serial.print (rangeVal);
Serial.println (" mmstage6"  );
       

if (counter4 == 0)             // checks the counter4 if it is 0   counter 4: evertime ,turn off the pump after valve closes 
{
   waittime = millis() + 100;    // set wait time for 100 milliseconds

 counter4 = 1;                  // makes the counter4 equal to 1
} 

        if ( millis() >= waittime)        // sets the condition when pump goes off after valve goes off
        {//Serial.print("millis 2:");       // prints millis
         //Serial.println(millis());
 
       digitalWrite(D8,LOW);                  //pump off       
       digitalWrite(D4,LOW);                //pump led off  
        
        
      if (rangeVal > 180)                       // if no hand
      {
        counter4 = 0;                            // counter4 equal to 0
        next_stage=getreading;                   //jumps to stage 1
      }
        }

       break;
default:
// clear interrupts //
   WriteByte(0x015,0x07);
   
  delay (100); // wait 0.1 seconds}
           }}} // end of loop

vl6180x application note.pdf (690 KB)

I have tried ASCII code on nano...it gives me ASCII table at all the baud rates..

That sounds reassuring.

on Nano board:
LED blink command with delay...Without serialmonitor it works perfectly, with serialmonitor opened, it just turned on.

LED blink without delay ... Without Serialmonitor it works perfectly, with serial monitor it blinks but Slow....

Really? That sounds odd. Did you disconnect everything when you did the blinks?

Yes, I have removed all the connections before running it..
Another behavior I have noticed that when I run code, LED on the board (13) blinks even though I have not coded for it... is it normal!?

I have attached my circuit herewith, unfortunately I am not able to download the software to draw the circuit and in online drawing tool, nano board and my sensor was not available....

Why not test with another Nano and see if the problem still exists.
Then we can be sure where to investigate further on.

Yes, I tried with new Arduino nano..but same results....it is still not running perfectly.. :frowning:

Have you tried the 10Kohm pull up resistor on I2C bus?