text:
Arduino oscilloscope
I have been working on a recent project to build an Arduino Oscilloscope interfaced with a 4X4 keypad membrane with Nokia 5110 LCD display.I have successful individual code fragments/portions which
1)Generate waves interfaced with the keyboard
2)Display the same on the Nokia LCD 5110
i am using the Arduino Due and the 1st part of my code generates waves on DAC1 with the code as follows:-
#include "Waveforms.h"
#include <Keypad.h>
#include <LiquidCrystal.h>

//Set the desired duty cycle in percentage

double dc,t,a,d;
long d_milli,d_micro,a_milli,a_micro,m,n;
int stage =0;

int sample_delay1;
LiquidCrystal lcd(A2, A3, A4, A5, A6, A7);
float sample_delay;
String num1,num2;
int wave1;
String wave_name;
double duty_cycle,k;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'.','0','#','D'}
};
byte rowPins[ROWS] = {23,25,27,29}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {31,33,35,37}; //connect to the column pinouts of the keypad
int i = 0;
int sample;
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
boolean in_setup = true;
void setup()
{
  Serial.begin(9600);
  analogWriteResolution(12);  // set the analog output resolution to 12 bit (4096 levels)
  analogReadResolution(12);
  lcd.begin(20,4);
  char key = customKeypad.getKey();
  lcd.setCursor(0, 0);
  lcd.print("choose wave: ");
  lcd.setCursor(0, 1);
  lcd.print("A=Sine");
  lcd.setCursor(8, 1);
  lcd.print("B=Triangular");
  lcd.setCursor(0, 2);
  lcd.print("C=Sawtooth");
  lcd.setCursor(11, 2);
  lcd.print("D=Square");

  while( true)
  {
        char key = customKeypad.getKey();
        if(stage == 0)
        {
              Serial.println("in stage 0");
              if(key == 'A' )
              {
                wave1 = 0;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print(" Sine?      ");
                wave_name ="Sinusoidal";
                Serial.println(wave_name);

              }
              else if(key == 'B')
              {
                wave1 = 1;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print("Triangular?");
                wave_name ="Triangular";
                Serial.println(wave_name);
              }
              else if(key == 'C')
              {
                wave1 = 2;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print("Sawtooth?  ");
                wave_name ="Sawtooth";
                Serial.println(wave_name);
              }
              else if(key == 'D')
              {
                wave1 = 3;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print("Square?    ");
                wave_name ="Square";
                Serial.println(wave_name);

              }
              else if(key == '#')
              {
                stage++;
                //lcd.clear();
                lcd.setCursor(0,1);
                lcd.print("Frequency=");
                Serial.println("Frequency=");
              }
        }
       else if(stage == 1)
        {
              if(key != NO_KEY &&(key=='1'||key=='2'||key=='3'||key=='4'||key=='5'||key=='6'||key=='7'||key=='8'||key=='9'||key=='0'))
              {
                num1 = num1 + key;
                //int numLength = num1.length();
                //to adjust one whitespace for operator
                lcd.setCursor(10,1);
                lcd.print(num1);
              }

              else if(key == '#')
              {
                    k = num1.toInt();
                    Serial.print(k);

                          int sample_delay_int = 1000000/(k*120);
                          float sample_delay_float = 1000000/(k*120);
                          float difference= sample_delay_float-sample_delay_int;
                          sample_delay1 = sample_delay_int - 6;
                          if(difference > 0.5)
                          {
                            sample_delay1++;
                          }

                          Serial.println(sample_delay1);
                          lcd.clear();
                          lcd.print(wave_name);
                          lcd.setCursor(0,1);
                          lcd.print("Frequency=");
                          lcd.print(num1);
                          lcd.print(" Hz");
                          break;
                  }
              }
   }
}

void loop()
  {
  analogWrite(DAC1, waveformsTable[wave1][i] );
  i++;
  if(i == maxSamplesNum)  // Reset the counter to repeat the wave
    i = 0;
  else
    delayMicroseconds(sample_delay1);
  }

Next, I input these waves from DAC1 into analog input A0 to display on the LCD with code as below:-
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <SPI.h>

#define DISPLAY_WIDTH 84
#define DISPLAY_HEIGHT 48

#define ARDUINO_PRECISION 1023.0
Adafruit_PCD8544 display = Adafruit_PCD8544(8,9,10,12,11);

//Analog Pins
int channelAI = A0;      // probe

#define DELAY_POTENTIMETER //disabled it I don't have it connected
#ifdef DELAY_POTENTIMETER
int delayAI = A1;       // delay potentiometer
#endif

float delayVariable = 0;
float scale = 0;
int xCounter = 0;
int yPosition = 0;
int readings[DISPLAY_WIDTH+1];
int counter = 0;

unsigned long drawtime = 0;
unsigned long lastdraw = 0;
int frames = 0;

void setup(void)
{
  display.begin();
  display.setContrast(30);// you might have a slightly different display so it might not be the optimal value for you
  display.clearDisplay();
}

void loop()
{
  #ifdef DELAY_POTENTIMETER
  delayVariable = analogRead(delayAI);
  delayVariable = (delayVariable/100);
  #endif
  scale = (float)(DISPLAY_HEIGHT-1)/ARDUINO_PRECISION;

  //record readings
  for(xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
  {
    yPosition = analogRead(channelAI);
    readings[xCounter] = (yPosition*scale);
    #ifdef DELAY_POTENTIMETER
    delay (delayVariable);
    #endif
  }

  display.clearDisplay();

  //Draw Voltage Ref Lines
  display.drawLine( 10, 0, 10, DISPLAY_HEIGHT-1, BLACK);
  display.drawLine( 5, (DISPLAY_HEIGHT-1)-(.2 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.2 *ARDUINO_PRECISION * scale), BLACK);
  display.drawLine( 0, (DISPLAY_HEIGHT-1)-(.4 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.4 *ARDUINO_PRECISION * scale), BLACK);
  display.drawLine( 5, (DISPLAY_HEIGHT-1)-(.6 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.6 *ARDUINO_PRECISION * scale), BLACK);
  display.drawLine( 0, (DISPLAY_HEIGHT-1)-(.8 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.8 *ARDUINO_PRECISION * scale), BLACK);
  //display.drawLine( 5, (DISPLAY_HEIGHT-1)-(.84 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.84 *ARDUINO_PRECISION * scale), BLACK);

  //Draw Voltage Ref Numbers
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.2 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.2));
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.4 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.4));
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.6 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.6));
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.8 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.8));

  for(xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
  {
    display.drawPixel(xCounter, (DISPLAY_HEIGHT-1)-readings[xCounter], BLACK);
    if(xCounter>1){
      display.drawLine(xCounter-1, (DISPLAY_HEIGHT-1)-readings[xCounter-1], xCounter, (DISPLAY_HEIGHT-1)-readings[xCounter], BLACK);
    }
  }
  //Draw FPS
  display.setCursor((DISPLAY_WIDTH-1)-11,0);
  display.print(frames);

  //Draw Voltage
  display.setCursor(((DISPLAY_WIDTH-1)/2),0);
  display.print(analogRead(channelAI)/ARDUINO_PRECISION*5.0);

  display.display();

  //Calculate FPS
  drawtime = micros();
  frames=1000000/*a second*//(drawtime-lastdraw);
  lastdraw = drawtime;
}

Now the problem arises when i try doing the 2 things on d same arduino due board.
I got perfect results when i used arduino due and arduino uno simultaneously but have not been able to generate waves on the LCD using the same board.
Is it possible to do the same. Can some1 help me incorporate the 2 programs into 1  ..Thanxx
I tried playing around with my setup() and loop() and have reached a point where my program does everything ,ie takes keypad input ,displays options on the LCD ,takes in freq and generates a splashscreen but the only thing i'm missing out on is d wave display on the LCD (I'm able to see the selected wave on the DSO) ..So i guess i'm pretty close, and the edited code is as follows:-
#include "waveforms.h"
#include <Keypad.h>
#include <SPI.h>

#include <Adafruit_GFX.h>
#include <gfxfont.h>

#include <Adafruit_PCD8544.h>

 //Set the desired duty cycle in percentage
Adafruit_PCD8544 display = Adafruit_PCD8544(8, 9, 10, 12, 11);
double dc,t,a,d;
long d_milli,d_micro,a_milli,a_micro,m,n;
int stage =0;

int sample_delay1;
float sample_delay;
String num1,num2;
int wave1;
String wave_name;
double duty_cycle,k,Z;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'.','0','#','D'}
};
byte rowPins[ROWS] = {23,25,27,29}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {31,33,35,37}; //connect to the column pinouts of the keypad
int i = 0;
int t_sample;

#define DISPLAY_WIDTH 84
#define DISPLAY_HEIGHT 48

#define ARDUINO_PRECISION 1023.0
//Adafruit_PCD8544 display = Adafruit_PCD8544(8,9,10,12,11);

//Analog Pins
int channelAI=A0;

#define DELAY_POTENTIMETER //disabled it I don't have it connected
#ifdef DELAY_POTENTIMETER
int delayAI = A1;       // delay potentiometer
#endif

float delayVariable = 0;
float scale = 0;
int xCounter = 0;
int yPosition = 0;
int readings[DISPLAY_WIDTH+1];
int counter = 0;

unsigned long drawtime = 0;
unsigned long lastdraw = 0;
int frames = 0;

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
boolean in_setup = true;
void setup()
{
  Serial.begin(9600);
  analogWriteResolution(12);  // set the analog output resolution to 12 bit (4096 levels)
  analogReadResolution(12);
  display.begin(20,4);

  char key = customKeypad.getKey();

  display.begin();
  display.display();
  display.setContrast(40);// you might have a slightly different display so it might not be the optimal value for you
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(BLACK);
  display.setCursor(0, 0);
  display.print("choose wave: ");
  display.display();
  display.setCursor(1, 8);
  display.print("A=Sine");
  display.display();
  display.setCursor(1,16);
  display.print("B=Triangular");
  display.display();
  display.setCursor(1,24);
  display.print("C=Sawtooth");
  display.display();
  display.setCursor(1,32);
  display.print("D=Square");
  display.display();

  while( true)
  {
    char key = customKeypad.getKey();
    if(stage == 0)
    {
      Serial.println("in stage 0");
      if(key == 'A' )
      {
        wave1 = 0;
        display.clearDisplay();
        display.setCursor(0,0);
        display.print(" Sine?      ");
        display.display();
        wave_name ="Sinusoidal";
        Serial.println(wave_name);

      }
      else if(key == 'B')
      {
        wave1 = 1;
        display.clearDisplay();
        display.setCursor(0,0);
        display.print("Triangular?");
        display.display();
        wave_name ="Triangular";
        Serial.println(wave_name);
      }
      else if(key == 'C')
      {
        wave1 = 2;
        display.clearDisplay();
        display.setCursor(0,0);
        display.print("Sawtooth?  ");
        display.display();
        wave_name ="Sawtooth";
        Serial.println(wave_name);
      }
      else if(key == 'D')
      {
        wave1 = 3;
        display.clearDisplay();
        display.setCursor(0,0);
        display.print("Square?    ");
        display.display();
        wave_name ="Square";
        Serial.println(wave_name);

      }
      else if(key == '#')
      {
       stage++;
       display.clearDisplay();
       display.setCursor(20, 8);
       display.println("Freq=");
       display.display();
       Serial.println("Frequency=");
      }
    }
    else if(stage == 1)
    {
      if(key != NO_KEY &&(key=='1'||key=='2'||key=='3'||key=='4'||key=='5'||key=='6'||key=='7'||key=='8'||key=='9'||key=='0'))
      {
        num1 = num1 + key;
        //int numLength = num1.length();
        //to adjust one whitespace for operator
        display.setTextSize(1);
        display.setTextColor(BLACK);
        display.setCursor(48, 9);
        display.print(num1);
        display.display();
      }
      else if(key == '#')
      {
        stage++;
        k = num1.toInt();
        Serial.print(k);
        display.setTextSize(1);
        display.setTextColor(BLACK);
        display.display();
        display.setCursor(10, 1);

        int sample_delay_int = 1000000 / (k * 120);
        float sample_delay_float = 1000000 / (k * 120);
        float difference = sample_delay_float - sample_delay_int;
        sample_delay1 = sample_delay_int - 6;
        if (difference > 0.5)
        {
          sample_delay1++;
        }

        display.display();
        Serial.println(sample_delay1);
        display.clearDisplay();
        display.print(wave_name);
        display.setCursor(1, 8);
        display.println("Freq=");
        display.print(num1);
        display.println(" Hz");
        break;
      }
    }
  }

  //record readings
  for(xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
  {
    yPosition = analogRead(A0);
    readings[xCounter] = (yPosition*scale);
    #ifdef DELAY_POTENTIMETER
    delay (delayVariable);
    #endif
  }

  display.clearDisplay();

  #ifdef DELAY_POTENTIMETER
  delayVariable = analogRead(delayAI);
  display.display();
  delayVariable = (delayVariable/100);
  #endif
  scale = (float)(DISPLAY_HEIGHT-1)/ARDUINO_PRECISION;

  //Draw Voltage Ref Lines
  display.drawLine( 10, 0, 10, DISPLAY_HEIGHT-1, BLACK);
  display.drawLine( 5, (DISPLAY_HEIGHT-1)-(.2 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.2 *ARDUINO_PRECISION * scale), BLACK);
  display.drawLine( 0, (DISPLAY_HEIGHT-1)-(.4 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.4 *ARDUINO_PRECISION * scale), BLACK);
  display.drawLine( 5, (DISPLAY_HEIGHT-1)-(.6 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.6 *ARDUINO_PRECISION * scale), BLACK);
  display.drawLine( 0, (DISPLAY_HEIGHT-1)-(.8 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.8 *ARDUINO_PRECISION * scale), BLACK);
  //display.drawLine( 5, (DISPLAY_HEIGHT-1)-(.84 *ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT-1)-(.84 *ARDUINO_PRECISION * scale), BLACK);

  //Draw Voltage Ref Numbers
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.2 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.2));
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.4 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.4));
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.6 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.6));
  display.setCursor(0,((DISPLAY_HEIGHT-1)-(.8 *ARDUINO_PRECISION * scale))-3);
  display.print((int)(5.0*0.8));

  for(xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
  {
    display.drawPixel(xCounter, (DISPLAY_HEIGHT-1)-readings[xCounter], BLACK);
    if(xCounter>1){
      display.drawLine(xCounter-1, (DISPLAY_HEIGHT-1)-readings[xCounter-1], xCounter, (DISPLAY_HEIGHT-1)-readings[xCounter], BLACK);
    }
  }
  //Draw FPS
  display.setCursor((DISPLAY_WIDTH-1)-11,0);
  display.print(frames);

  //Draw Voltage
  display.setCursor(((DISPLAY_WIDTH-1)/2),0);
  display.print(analogRead(A0)/ARDUINO_PRECISION*5.0);

  display.display();

  //Calculate FPS
  drawtime = micros();
  frames=1000000/(drawtime-lastdraw);
  lastdraw = drawtime;
  display.display();
}

void loop()
{
  analogWrite(DAC1, waveformsTable[wave1][i] );
  i++;
  if(i == maxSamplesNum)  // Reset the counter to repeat the wave
    i = 0;
  else
  delayMicroseconds(sample_delay1);

  analogWrite(DAC0, waveformsTable[wave1][i] );
  i++;
  if(i == maxSamplesNum)  // Reset the counter to repeat the wave
    i = 0;
  else
    delayMicroseconds(sample_delay1);
}

Can some1 possibly tinker around with this ..It'll b a huge help!!

Can you reprogram your signal generator to work on timer interrupts, so the oscilloscope code (+ keypad handling) runs while being interrupted by the wave generation?

Also, I believe you can slightly increase your FPS by moving the "static" part of the drawing in setup(), and greatly by not using the adafruit library - AFAIK it uses offscreen buffer on 5110 and redraws the entire screen. Instead you just write directly to the screen, one or 2 writes per column (one to erase the old samlple and one to draw the new one, unless they overlap - then it is one write) - just draw pixels (actually 8 pixels at once) for each column.

You have two programs. One has a very complicated setup(), but a very quick loop(). The other has a very small setup(), but a very complicated loop(). And you want to merge the two programs?
That will be very, very difficult. Your first program loop() looks like this:
void loop() {
   analogWrite(...); // Very quick code
   i++;              // Very quick code
   if (..)           // Very quick code
      i = 0;         // Very quick code
   else              // ***BUG!!!*** This shoud not be here!
   delayMicroseconds(...); // Very specific timing delay
} // loop()

In other words, to produce the correct waveform it does very few instructions very quickly - and then waits a carefully calculated time.
Your other program's loop() does lots of things, and doesn't care about timing. The code is not time-sensitive at all - and writing to the display takes variable time anyway.
Your only choice is to set a timer to interrupt every sample_delay1 microseconds, and inside the timer interrupt handler do the analogWrite(...); call instead of having the loop() function do it. That is Advanced Arduino programming!

Thanx a lot @John Burger! I tried playing around with my setup() and loop() and have reached a point where my program does everything ,ie takes keypad input ,displays options on the LCD ,takes in freq and generates a splashscreen but the only thing i'm missing out on is d wave display on the LCD (I'm able to see the selected wave on the DSO) ..So i guess i'm pretty close, and the edited code is as follows:-

I've included the edited code in my original question ..KIndly have a look,c if u can tinker around with the code! Thanx a lot

The reason that you are not seeing the wave display is that you're not generating it in loop(). You do understand that setup() is performed once, and when that finishes loop() is called repeatedly. In your edited version you have drawn the wave display once in setup(). Your loop() only generates (now two) waveforms - it needs to also draw the wave, but that will disturb the timing of the waveforms. And now that you're generating two waveforms, why are you waiting sample_delay1 twice? You are also incrementing i twice. You've made it very complicated for yourself!

Yeah you're right!@John Burger! A possible solution to the problem dat i came across was parallel programming..I load 1st part of the code on arduino uno ,2nd part on the 'Due' and program them to run simultaneously.Bt is this feasible?? N do u have any idea of parallel programming possibly,coz i have absolutely no experience of it.

There's no need to do the sort of "parallel programming" that you describe - unless you have the boards necessary, of course! Re-read my answer, paying particular attention to the final paragraph. You can do everything that you want with Timer Interrupts - but we can't give you a course on that from StackExchange! Read, read, read everything you can get your hands on...


text:
code for line following robot not working perfectly
I have made a line following robot using 2 IR sensor. My line following robot was working successfully with this code.
#define LS 2      // left sensor
#define RS 3      // right sensor

/*-------definning Outputs------*/
int LM1= 5;       // left motor
int LM2= 6;     // left motor
int RM1= 9;       // right motor
int RM2= 10;

void setup()
{
  pinMode(LS, INPUT);
  pinMode(RS, INPUT);
  pinMode(LM1, OUTPUT);
  pinMode(LM2, OUTPUT);
  pinMode(RM1, OUTPUT);
  pinMode(RM2, OUTPUT);
}

void loop()
{
  if(digitalRead(LS) && digitalRead(RS))     // Move Forward
  {
    digitalWrite(LM1, HIGH);
    digitalWrite(LM2, LOW);
    digitalWrite(RM1, HIGH);
    digitalWrite(RM2, LOW);
  }
 else if(!(digitalRead(LS)) && digitalRead(RS))     // Turn right
  {
    digitalWrite(LM1,HIGH);
    digitalWrite(LM2, LOW);
    analogWrite(RM1,70);
    digitalWrite(RM2,LOW);
  }
  else if(digitalRead(LS) && !(digitalRead(RS)))     // turn left
  {
    analogWrite(LM1,70);
    digitalWrite(LM2, LOW);
    digitalWrite(RM1,HIGH);
    digitalWrite(RM2,LOW);
  }else{
    digitalWrite(LM1, LOW);
    digitalWrite(LM2, LOW);
    digitalWrite(RM1,LOW);
    digitalWrite(RM2, LOW);
  }
}

As I used only two sensor,sometimes it goes out of the line. So I have tried to make an advanced line following robot which could get back to track automatically when it goes out of the line.But the code is taking only the 1st value of tmp.(tmp=1) even when left sensor touches the line after white sensor and the robot goes out of the line.The value of tmp should be 2 when the robot goes out of the line and the left sensor touches the line after the white sensor.  Here is the code:
/*-------definning Inputs------*/
#define LS 2      // left sensor
#define RS 3      // right sensor

/*-------definning Outputs------*/
int LM1= 5;       // left motor
int LM2= 6;      // left motor
int RM1= 9;       // right motor
int RM2= 10;  //right motor
int tmp;

void setup()
{
  pinMode(LS, INPUT);
  pinMode(RS, INPUT);
  pinMode(LM1, OUTPUT);
  pinMode(LM2, OUTPUT);
  pinMode(RM1, OUTPUT);
  pinMode(RM2, OUTPUT);
}

void loop()
{
  if(digitalRead(LS) && digitalRead(RS))     // Move Forward
  {
    digitalWrite(LM1, HIGH);
    digitalWrite(LM2, LOW);
    digitalWrite(RM1, HIGH);
    digitalWrite(RM2, LOW);
  }
 else if(!(digitalRead(LS)) && digitalRead(RS))     // Turn right
  {
    digitalWrite(LM1,HIGH);
    digitalWrite(LM2, LOW);
    analogWrite(RM1,70);
    digitalWrite(RM2,LOW);
    tmp=1;
  }
  else if(digitalRead(LS) && !(digitalRead(RS)))     // turn left
  {
    analogWrite(LM1,70);
    digitalWrite(LM2, LOW);
    digitalWrite(RM1,HIGH);
    digitalWrite(RM2,LOW);
    tmp=2;
  }
  else//out of the line
  {
    if(tmp=1){
      analogWrite(LM1,70);
      digitalWrite(LM2, LOW);
      digitalWrite(RM1,LOW);
      analogWrite(RM2,70);
    }else if(tmp=2){
      digitalWrite(LM1,LOW);
      analogWrite(LM2, 70);
      analogWrite(RM1,70);
      digitalWrite(RM2,LOW);
    }
  }
}

This test:
if (tmp = 1)

is always true. You are assigning 1 to tmp and that value (1), when
interpreted in a boolean context (i.e. as a truth value), is true.
You probably mean
if (tmp == 1)

and similarly for the next test.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

sort: votes


text:
How to blink led and run another code at same time?
I had written a code to calculate rpm of the motors using IR sensor and
Arduino nano and displaying it on OLED . With that I want an LED to
blink always. Here is the code what I did:
You can skip the declarations and setup() part. Just move directly
to loop(). I have problem in loop. In loop(), only LED goes on
blinking and further rpm calculation with OLED displaying codes are not
performed.
#include "avr/sleep.h"
#include "avr/power.h"
#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"

#define OLED_RESET 4

Adafruit_SSD1306 display(OLED_RESET);

int led = 12;
int in = 13;
int pushbutton=10;
unsigned long duration = 0;
float rpm = 0;
float rpm_a = 0;
int counter = 0;
int present = 0;
int previous = 0;
unsigned long elapsed = 0;
unsigned long elapsed_prev = 0;
int disabled = 0;

void setup() {
    Serial.begin(9600);
    pinMode(led, OUTPUT);
    pinMode(in,INPUT);
    pinMode(pushbutton,INPUT);
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(35,1);
    display.print("xyz");
    display.display();
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(25,13);
    display.print("abc");
    display.display();

    delay(5000);

    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0,0);
    display.println("RPMmeter");
    display.display();
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(0,19);
    display.println("RPM:");
    display.setCursor(80,19);
    display.println(rpm);
    display.display();

    elapsed = micros();
}

void loop()
{
    /** led blink part **/
    digitalWrite(led, HIGH);
    delay(70);
    digitalWrite(led, LOW);
    delay(70);
    digitalWrite(led, HIGH);
    delay(70);
    digitalWrite(led, LOW);
    delay(900);

    /** led blink part over and rpm calculation and displaying on
     * oled part starts **/

    if(digitalRead(pushbutton))
    {
        //Arduino low power enabled
        if(disabled==0)
        {
            sleep_disable();
            disabled = 1;
        }
        if (digitalRead(in) == 1 && previous == 0)
        {
            previous = 1;
            duration = elapsed - elapsed_prev;
            elapsed_prev  = micros();
        }
        if (digitalRead(in) == 1 && previous == 1)
        {
            previous = 1;
        }
        if (digitalRead(in) == 0 && previous == 1)
        {
            previous = 0;
        }
        if (digitalRead(in) == 0 && previous == 0)
        {
            previous = 0;
            elapsed = micros();
        }

        rpm = 60000000/duration;

        //We add a small error in the rpm value (in this case +-2)
        if ((rpm_a-2) < rpm  &&  rpm < (rpm_a+2))
        {
            rpm_a = rpm;
            counter = counter + 1;
            if (counter == 50)
            {
                display.clearDisplay();
                display.setTextSize(1);
                display.setTextColor(WHITE);
                display.setCursor(0,0);
                display.println("JARVIS RPMmeter");
                display.setTextSize(2);
                display.setTextColor(WHITE);
                display.setCursor(0,19);
                display.println("RPM:");
                display.setCursor(80,19);
                display.println(rpm);
                display.display();
                counter = 0;
            }
        }
        if (!( (rpm_a-2) < rpm  &&  rpm < (rpm_a+2)))
        {
            rpm_a=rpm;
        }

    }//end if pushbutton=1
    else {
        display.display();
        display.clearDisplay();
        delay(10);
        duration = 0;
        rpm = 0;
        rpm_a = 0;
        counter = 0;
        present = 0;
        previous = 0;
        //Arduino low power enabled
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        sleep_enable();
        disabled = 0;
    }
}

This was the code. The problem is without that led blinking code
part in the loop, the code works fine, but if we include that LED
blinking part, the code doesn't move further. I mean only LED goes on
blinking and further codes are not performed. Why is it so? And how to
make both rpm calculation with display on OLED as well as LED
blinking happen through a single code simultaneously?

Don't use delay. Instead non-blocking code like in the BlinkWithoutDelay example of the Arduino IDE. How this is done is described in many many tutorials and also questions on this site.

@userLP, it would help if you would pick the answer which proved to be correct and mark it such so future visitors will know which answer worked for you.

Look at my answer to a similar question. Apply the same principle to your problem:

Move each task (blinking; calculating RPM) into its own separate function.
Make loop() call those functions as often as possible.
Make each function decide whether it is time to do its task, do it or not, and return.
Those functions must never wait.

This kind of program organization - called non-blocking - is extendable to as many tasks as you wish, until you run out of memory, or the processor runs out of time to do everything as fast as you need it to (that will be a great many more than the two you've described!).

While executing the 'Delay' commands your arduino doesn't really do anything. The best thing you can do is have a look at BlinkWithoutDelay and adapt your code accordingly.

There are a few options to use millis() for this.
Is it okay if I change the 900ms into a multiple of 70ms? Then I can count intervals of 70ms.
// blink led: 70ms on, then 70ms off, then 70ms on, then 910ms off

unsigned long previousMillis;
int count = 0;

void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis >= 70) {
    previousMillis = currentMillis;

    switch(count) {
      case 0:
        digitalWrite(13, HIGH);
        break;
      case 1:
        digitalWrite(13, LOW);
        break;
      case 2:
        digitalWrite(13, HIGH);
        break;
      case 3:
        digitalWrite(13, LOW);
        break;
    }
    count++;

    if(count >= 16)
      count = 0;
  }
}

When the values of the intervals are in a array, then the code is probably smaller.
// blink led: 70ms on, 70ms off, 70ms on, 900ms off

unsigned long previousMillis;
const int intervals[4] = {70, 70, 70, 900};
int index = 0;

void setup() {
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);  // turn led on, after 70ms it will be turned off
}

void loop() {
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis >= intervals[index]) {
    previousMillis = currentMillis;

    int level = (index % 2) == 0 ? LOW : HIGH;
    digitalWrite(13, level);

    index++;

    if(index > 3)
      index = 0;
  }
}

This second sketch is smaller, but I prefer the first one.

The only thing that I can see that makes your code faulty is the fact that you use a if statement to check if your button is pushed and then you have a lot of code to be executed in that statement rather set up a bool outside of your loop and set it with the if function then use a while to do all the rest of the work that was in your if statement that way when the button is released the code will still be executed and when it is pressed again it will happen again
Almost forgot the good stuff yes the blinkwithoutdelay is the way to go on the blink code

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Printing the array using print and serial write function in Arduino Uno
I have, one program with only using printing array and other with serial write and print function for the array, while using serial write and print function I get these extra characters between the data as shown below, can anyone help me with this
Printing the array with print function
uint8_t a[13] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0X77, 0x88,
                 0x01, 0x02, 0x03, 0x04, 0x05};
int i;

void Print_Hexa(uint8_t num) {
  char Hex_Array[2];

  sprintf(Hex_Array, "%02X", num);
  Serial.print(Hex_Array);
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  for (i = 0; i <= 12; i++) {
    //Serial.write(a[i]);
    Print_Hexa(a[i]);
  }
  Serial.println();
  delay(100);
}

Using with serial write and print function for array
uint8_t a[13] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0X77, 0x88,
                 0x01, 0x02, 0x03, 0x04, 0x05};
int i;

void Print_Hexa(uint8_t num) {
  char Hex_Array[2];

  sprintf(Hex_Array, "%02X", num);
  Serial.print(Hex_Array);
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  for (i = 0; i <= 12; i++) {
    Serial.write(a[i]);
    Print_Hexa(a[i]);
  }
  Serial.println();
  delay(100);
}

Serial.write(a[i]); sends a character but not all values are readable characters

To prevent buffer overruns, use snprintf(Hex_Array, sizeof(Hex_Array), "%02X", num);. More info here and here. Also be aware that the Arduino versions don't support the %f format specifier.

Serial.write(some_byte) writes a byte on the serial output. The
Arduino serial monitor tries to interpret the bytes it receives as text:

0x11 is a control character, displayed as “□”
0x22 is the ASCII code for the double quote (")
0x33 is the ASCII code for the digit 3.
0x44 is the ASCII code for the uppercase letter “D”
etc.

Is it possible to remove them or mask them if possible

@voticoy: Sure! Remove the Serial.write() statement.

To store a 2 character string you need a 3 byte array, not a 2 byte array. This is because in C a string consists of the actual string data and a zero ("NULL") byte at the end to indicate where the end of the string is.
So you would need:
char Hex_Array[3];

so it can store, for the number 0x69: 69\0. Otherwise you overrun the array and corrupt other data that follows in the stack, and changing that other data corrupts your string by changing the "end of string" marker to some other random ASCII character.

Thank you for the response, I changed the array size to 3 as mentioned, still in the serial monitor output remains the same.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Why won't my servo and ultrasonic sensor work together?
I have a school project due tomorrow, and I'm planning to connect a servo motor with an ultrasonic sensor. If the distance is under 10cm, the servo motor should turn 180 degrees and will return to 0 degrees when there's no object in front of the sensor. I've tried them separately, the sensor by itself works and could read distance as usual and the servo works too. However, when I put the two code together, it just seems to cancel each other out. I don't know much about coding but pretty sure the sensor is supposed to print the distance on the serial monitor, but it just stops working, I also put some code to try and get the servo to turn, but it also doesn't work... So now I'm stuck pls help me, it's due tomorrow :(
Could it be my power source? I'm using my laptop to power it... but my friend did the same project, and it worked well using laptop as a power source, but i saw some post like this that encourages me to change power source, but isn't a laptop a huge power source? (genuinely asking)
#include <Servo.h>
#define servopin 9
#define echoPin 4
#define trigPin 5

Servo Myservo;
int long duration;
int distance;

void setup() {
    Myservo.attach(servopin);
    pinMode(echoPin, INPUT);
    pinMode(trigPin, OUTPUT);
}

void loop() {
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);

    duration = pulseIn(echoPin, HIGH);
    distance = (duration * 0.034 / 2);

    if (distance < 10)
    {
        Myservo.write(180);
    }
    else
    {
        Myservo.write(0);
    }
    delay(500);
}

you have no debugging code ... add some ... right now, you have no way to know the value of distance

"but isn't a laptop a huge power source? " Most USB ports are only obliged to supply 500mA.  In fact, some will go into constant current mode to protect the computer.

I tried your code on online simulator, and it works perfect!
Maybe just try another distance check like if(distance<30) (at least) and let's know what will happen.
I don't think using the laptop as a power source is your problem

I know rightt, this is very confusing. It works fine on tinkercad but it won't work in real life, I'll try your suggestion. Thanks a lot :D


text:
Compilation error: 'Serial' does not name a type
#include <IRremote.h>

IRrecv IR (11);

Serial.begin(9600);

void setup() {
  // put your setup code here, to run once:
  IR.enableIRIn();
}

void loop() {
  // put your main code here, to run repeatedly:
  if (IR.decode()){
    Serial.println(IR.decodedIRData.decodedRawData, HEX);
    delay(1500);
    IR.resume();
  }
}

In C & C++, executable statements must be within a function. Your third statement, Serial.begin(9600); is (or should be) executable but since it is outside any function, the compiler tried to interpret it as a declaration - thus, the error.


text:
How to manage interrupt from accelerometer BMA220?
I would like to use the interrupt register from the BMA220 accelerometer in order to detect high-g shock. I am using a Mega2560 and the sensor is powered by 3.3 V. I use a voltage divider to convert the 5V from the card to 3.3V because the 5V pin gives more current. The memory map concerning the registers is shown below
In the datasheet the section concerning high-g registers is as followed :

It is written that whenever a condition is met for the interrupt controller "an interrupt (logic '1') is issued through the INT pin of the sensor."
However after initializing the necessary registers (in I2C):

0xC for high_th
0xA for high_hy and high_dur
0x1C for en_high_x/y/z

I don't get my interrupt working. Using a voltmeter I always get a high value (3.3V) on the INT pin of my accelerometer eventhough it stays still and I wrote a threshold of 2G...
Here is the code I am using :
#include <BMA220.h>
#include "SEN0168.h"

BMA220 bma;
byte interruptPin = 2;
byte count = 0;
const uint8_t HIGH_SET = 0xA;
const uint8_t HIGH_LOW_TH = 0xC;
const uint8_t INTERRUPT_REG = 0x18; // to get the bit indicating an interrupt was detected, not used because of the INT pin
const uint8_t ENABLE = 0x1C;

void setup() {
   Serial.begin(74880);
   pinMode(interruptPin, INPUT);
   init_SEN0168(R4); // set sensitivity to 4G
   bma.setRegister(ENABLE, 0xF7); // enable high-g-detection, reset interrupt bit control and latch permanently
   bma.setRegister(HIGH_LOW_TH, 0x1); // Threshold of 1G
   bma.setRegister(HIGH_SET, 0x1); // No hysteresis and 2 signals needed to trigger
   attachInterrupt(digitalPinToInterrupt(interruptPin),counter, HIGH);
}

void loop() {
    if (count==1){
    Serial.print("x-axis: ");
    Serial.println(accel_range_SEN0168(X,R4));
    Serial.print("y-axis: ");
    Serial.println(accel_range_SEN0168(Y,R4));
    Serial.print("z-axis: ");
    Serial.println(accel_range_SEN0168(Z,R4));
    count =0;
    bma.setRegister(INTRP_RES_REG, 0xF7); // enable high-g-detection, reset interrupt bit control and latch permanently
    }
    else{
      Serial.println("No shock");
      count =0;
    }
}

void counter(){
  count +=1;
}

Am I missing something to clear in one register ? Or maybe since the card is in 5V and the sensor 3.3V logic there is a problem to detect change on the interrupt pin ?  Also I don't know if I understand properly the "logic 1". For me it means it puts the pin to "HIGH".
I use a part of the library written by Sönke Carstens-Behrens to set the registers from here : https://github.com/scbrac/BMA220.
I really need this interrupt pin to work...
Thank you for your help !

I use a voltage divider to convert the 5V from the card to 3.3V because the 5V pin gives more current. errr.... NO!  https://majenko.co.uk/blog/why-you-cant-use-resistors-voltage-regulator

Ok thank you for the article it answers simply the problem of voltage divider ! So it means I just cannot make my device work properly without a voltage regulator ? However I used to record some data that way and it was working. Appart from this, is there something in my code that shouldn't work ?

I am not too familiar with that unit, so I can't be sure.  However, you don't need a voltage regulator. Just use the 3.3V pin to power it. On modern Arduinos the 3.3V pin can provide plenty of power. The old rumour that 3.3V is limited to 50mA is wrong, and has been for many years.

Ok I will use the 3.3V then, thank you ! Has anybody an idea about the logic 1 interrupt ?

You should, at least for testing, set lat_int to 0b111 so it latches the interrupt on the pin until you manually reset it by setting reset_int to 1.  At the moment you have such a brief interrupt that you'll be hard pressed to see it even if it does trigger.

Ok so I tried to change the latch duration for many values in the register 0x1C as you can see in the updated code (for permanent latching) but still no detection of the shock... and the threshold is set to only 1G with no hysteresys

By changing HIGH to LOW of the interrupt I get record from the accelerometer but it doesn't respect the high-g condition...

The interrupt should be RISING, FALLING or LOW. There is no HIGH.

Ok but it is written that when a condition is met a logic 1 will be sent via the INT pin. How am I suppose to detect it ? Also I made a mask to get the bit corresponding to high_int (set to 1 if an interrupt has been triggered) in register 0x18 and this bit is always 1 ! I don't understand...

You would use RISING, which is a change from LOW to HIGH to catch the interrupt. As to why it's always HIGH I have no idea.  However most INT pins I have come across are active LOW not active HIGH...

I tried both RISING and LOW but I don't get the expected behaviour by the accelerometer... So nobody has experience with this accelerometer to share ?

Maybe on ee.se they may. It's more general electronics than Arduino really.

ee.se ? It tells me the website doesn't exist

It's shorthand for electronics.stackexchange.com

Oh ! OK I didn't know sorry ^^'... Well thank you for help Majenko !

That's ok... my fault for assuming everyone had the same strange mind as I do :P  I was using my phone, so easier to type shorthand on there.

EE.se has people that are more likely to understand the internal configuration of the chip and have experience with it.  You should take the Arduino out of the mix for the interrupt reading and instead connect it to an oscilloscope or logic analyser that can independently confirm the presence or not of an interrupt event.  Once you are happy that the interrupt is being configured correctly and is occurring on the pin as you require it to then you can start tackling the Arduino code to read the interrupt.

Thanks it is what I am doing right now and I hope I will get the result I want !

Majenko maybe you know what does this mean : 1 LSB is 2*(LSB of acc_data) ? Because now I get a better behaviour of my accelerometer but I wrote 0x8 for the threshold which is surely not 8G according to the shake I give to it

The least significant bit of the value is double the least significant bit of the accelerometer data.  So 1 is 0.5g, 2 is 1g, 3 is 1.5g, etc. Or that's my interpretation

Ok it is what I was thinking too ! Thanks ! What is funny is that when I put 0x8 I have a better behaviour of the interrupt but I should get 4G threshold which is surely not what I am giving the accelerometer. When I put 0x4 it activates the INT pin too often eventhough I just move slightly the sensor...Maybe I should play with hysteresis now


text:
Arduino due erase button and power switching
Last days I have been investigatin schematics of arduino due board. The purpose of proper understanding of schematics in crucial for me, beacuse I indend to build myself my own board with some minor modifications.
I would really want to learn something from it and not just blindly copy stuff that are already done. In schematics there are two things that I do not understand. First is the working principle of erase button (see: erase button). I have my own idea how does it work, but would like to clarify the working principle from someone that know exactly what is the purpose of all the elements that are connected to erase button. Also, why is ERASE_CMD  line connected to Atmega processor?
 Second thing is switching of power supply between external power and both usbs (see: usb switch). Again, would someone please just brifly describe working principle? Here I really do not undertand why is there op amp added?
Thank you in advance.
Erase button:

USB switch:

PLEASE NOTE: Both pictures are taken from original arduino webpage: https://store.arduino.cc/due  (see: documentation -> schematics)

The asker posted the same question and received an answer here
There is discussion regarding the purpose of the Erase switch here

You're encouraged to summarize the essentials such that the answer will remain useful if the links become broken.


text:
Why does the transistor burn out
I have an arduino uno which turns on a water pump (12V, 3.6W) once every 10 hours for a few minutes (I've followed this tutorial on how to connect the water pump). To turn on the water pump I used a PN2222A transistor, and connected the base in serial with a 220 ohm resistor to the digital pin 9.
A few minutes after turning on the power on my Arduino UNO the PN2222A transistor burned out (lots of smoke coming out of it).
I also used a 1N4007 diode, cathode connected to the positive pin, and anode to the negative pin of the water pump.
The power supply outputs around 12.6V
Maybe the resistor is too low/weak?
I've created a schematic here, attached it's a snapshot of it.

EDIT1:
Here is a picture on how I connected my transistor. I've removed from the photo:

the input wires (should be top-right of breadboard)
wire to arduino digital pin (should be on h-19 on the breadboard)
water pump from the breadboard (positive pin: c-2, negative pin: h-2)

EDIT2 (a solution that worked for me):
It looks like the input to the arduino (arduino and the pump share the same 12V input, but the arduino's goes through a step down converter to 10V) was a bit loose (to be more specific, the negative pin was loose) and randomly, the arduino would shut down and then the pump would start (maybe because the digital pin becomes HIGH, dont know why though) all while the arduino is shut off. That's when the transistor (PN2222A) burned out. I switched to TIP120 with a 1k resistor as @Jot suggested and looks like when the same problem with the power happens, nothing is burning out :)

That transistor is too small. The 3.6 Watt could be the average power usage. Do you have details of that pump? What is the maximum current? Use a darlington transistor that can drive a few amps or a mosfet.

@Jot I used this one. They say it is a 4.2W pump on the website, but on the pump is written 3.6W. Do you think a TIP120 will work ok?

It says "Max rated current: 350mA", so the PN2222A should be able to do that. Perhaps that information is not reliable or perhaps it has a peak current when it starts. The TIP120 is okay, you can use a resistor from the base to pin 9 of 1k, but you can also try with the 220 ohm.

It looks like the input to the arduino (arduino and the pump share the same 12V input, but the arduino's goes through a step down converter to 10V) was a bit loose (to be more specific, the negative pin was loose) and randomly, the arduino would shut down and then the pump would start (maybe because the digital pin becomes HIGH, dont know why though) all while the arduino is shut off. That's when the transistor (PN2222A) burned out. I switched to TIP120 with a 1k resistor as you suggested and looks like when the same problem with the power happens, nothing is burning out :)

I am not an electronics expert, but I too tried controlling a 12v circuit from arduino my first attempts were with transistors and always had problems with either switching on or switching off (depending upon the actual transistor).  Eventually I discovered MOSFETs and my project has been working perfectly ever since (continuous 24x7 for over 1 year). Wouldn't a MOSFET be better for this?

Mosfets are better. The TIP120 is very old, but easy to use. When it turns on with a constant large current, then it will become hot. A good mosfet stays cool.

Note: P2N2222A seems to have a different pinout to PN2222A.

@AlexBuicescu Please remove Edit2 from your post and instead add it as one of the answers.

It looks like the input to the arduino (arduino and the pump share the same 12V input, but the arduino's goes through a step down converter to 10V) was a bit loose (to be more specific, the negative pin was loose) and randomly, the arduino would shut down and then the pump would start (maybe because the digital pin becomes HIGH, dont know why though) all while the arduino is shut off.
That's when the transistor (PN2222A) burned out. I switched to TIP120 with a 1k resistor as @Jot suggested in one of the comments and looks like everything is ifne now (even when the same problem/bug with the power randomly happens)

By this, does it mean that you still have a problem turning the pump on? Because a PN2222A should handle up to 1A through its collector, as the datasheet states http://www.mouser.com/ds/2/149/PN2222A-371983.pdf

That's when the transistor (PN2222A) burned out. I switched to TIP120 with a 1k resistor as @Jot suggested and looks like when the same problem with the power happens, nothing is burning out :)

If you are still having problem turning the pump on, try turning it on manually by moving the jumper that is on the Arduino pin 9 to either GND or 5V, that should indicate if the problem lies on the Arduino pin (GPIO) or on the transistor.
It is also important to check the current needed by the pump, because the datasheet indicates that, to have a current IC = 350 mA -> IB = 35 mA which is close to the maximum of an Arduino pin (40 mA). If the Arduino pin cannot supply enough current to put the transistor in saturation mode, it will either kill the pin or put the transistor in its linear region, meaning it will dissipate a lot of power (Ic*Vce).

Base-Emitter Saturation Voltage
IC = 150 mA, IB = 15 mA
IC = 500 mA, IB = 50 mA

Yes, the TIP120 fixed the problem. The pn2222a was doing a great job while the arduino was powered on (it could keep the pump turned on for more than 20-30 seconds without issue), but when the arduino got shut off, the pump turned on and the transistor burned out after 4-5 seconds

TinkerCAD may have mislead you on the pinout for the transistor
TinkerCAD

PN2222A

Thanks for the quick response @markshancock, but I think I did use the correct pinout (unlike tinkercad). I edited the post with a photo my partial breadboard.

Seems to be a simple pinout issue, I checked the PN2222A and its pins are in EBC order. You probabily reversed it and burned the transistor. Reverse the transistor and the problem will be solved.

simulate this circuit – Schematic created using CircuitLab

Hi, I edited the post with more information about my pinout (also see the comment to @markshancock answer)

Note: P2N2222A seems to have a different pinout to PN2222A.

Datasheet for the PN2222A indicates it is only good for 150mA Ic for a pulse test, pulse width <= 300 microseconds, 2% duty cycle.
Your water pump, 12V, 3.6W.  With P=IV, or P/V = I, then 3.6W/12V = 0.3A, indicates this transistor is not the correct choice for this application.

These aren't the values I have seen on their datasheet in the past. Eg. this one from OnSemi. Can you link to a datasheet that backs up your values?

I pulled the data from the Mouser link in the answer from jDAQ, http://www.mouser.com/ds/2/149/PN2222A-371983.pdf  See Page 3 and Note 4.  Also the discussion of how it takes 50mA Ib to allow 500mA Ic, which an Arduino can't supply directly without damaging an I/O pin.  The OnSemi datasheet has a similar note "* Pulse Test: Pulse Width≤300µs, Duty Cycle≤2%" for "IC=500mA, IB=50mA ".

Thanks. You should note in your answer that that is for an Ib of 15mA. Two transistors in a Darlington pair would do the job

I think I'd have suggested a low Rds P-channel MOSFET instead, or an even lower Rds N-channel MOSFET to sink current thru the motor vs sourcing to it, but that was not the question asked.

I totally agree. Perhaps that should be (a separate) answer (ie. the transistor can't provide the power needed given the current the Arduino can supply to the base, use a MOSFET instead).


text:
Functions delaying gesture sensor recognition
I am working on a simple little robot to cure my boredom and all it has is a 64 x 32 OLED for the eyes, and a PAJ7620 Gesture recognition sensor with a Seeeduino Xiao as the main board.
Basically, when people swipe above the head where the sensor is, the robot will show the heart eyes. There are different reactions for different actions and all this is controlled through functions. When the sensor does not detect anything, the robot is supposed to cycle through a certain void which is determined based on how much it 'likes' the person.
Right now though, it just cycles through the function and does not respond to the sensor. My code is very inefficient because of all the functions, but it makes it more readable and more easily editable. With all my functions, the gesture sensor takes too long to respond to the actions.
What can I do to fix this? Can someone please help or give advice on how I can improve my code?
    #include <Arduino.h>
    #include <U8g2lib.h>
    #include <Wire.h>
    #include <DFRobot_PAJ7620U2.h>

    int like_score = 3;//Score for how much the bot likes you: this will impact which voids are used.
    int max_like_score = 17;
    char buffer[9];

    unsigned long previousMillis = 0;
    const long interval = 1000;

    DFRobot_PAJ7620U2 paj;

    U8G2_SSD1306_64X32_1F_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

    // fonts https://github.com/olikraus/u8g2/wiki/fntlistall#4-pixel-height
    void setup(void) {
      u8g2.begin();
      Serial.begin(115200);
      delay(300);
      u8g2.clearBuffer();
      Serial.println("Gesture recognition system base on PAJ7620U2");
      while (paj.begin() != 0) {
        Serial.println("initial PAJ7620U2 failure! Please check if all the connections are fine, or if the wire sequence is correct?");
        delay(500);
      }
      Serial.println("PAJ7620U2 init completed, start to test the gesture recognition function");
      paj.setGestureHighRate(true);
    }

    void normalL() {       //normal forward expression
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, normal);
      u8g2.sendBuffer();
    }
    void blinkL() {        //blinks
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blink);
      u8g2.sendBuffer();
    }
    void left() {          //looks left
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blinkleft);
      u8g2.sendBuffer();
    }
    void right() {         //looks right
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blinkright);
      u8g2.sendBuffer();
    }
    void angryL() {        //angry
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, angry);
      u8g2.sendBuffer();
    }
    void loveL() {         //in love
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, love);
      u8g2.sendBuffer();
    }
    void sleepL() {        //sleeping
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, sleep);
      u8g2.sendBuffer();
    }
    void susL() {          //suspicious
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, sus);
      u8g2.sendBuffer();
    }
    void stunL() {         //looks stunned
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, stun);
      u8g2.sendBuffer();
    }
    void upL() {           //Looks up
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, up);
      u8g2.sendBuffer();
    }
    void gleeL() {
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, glee);
      u8g2.sendBuffer();
    }
    void randomEx() {
      int rand = random(1, 8);
      if (rand == 1) {
        normalL();
      } else if (rand == 2) {
        left();
      } else if (rand == 3) {
        right();
      } else if (rand == 4) {
        angryL();
      } else if (rand == 5) {
        loveL();
      } else if (rand == 6) {
        susL();
      } else if (rand == 7) {
        upL();
      } else if (rand == 8) {
        gleeL();
      }
    }

    void likeRoutine() {
      normalL();
      delay(random(1000, 6500));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 4500));
      randomEx();
      delay(random(1000, 4500));
      blinkL();
      delay(90);
      loveL();
      delay(random(2500, 4000));
      blinkL();
      delay(90);
    }
    void kindofLikeRoutine() {
      normalL();
      delay(random(1000, 7000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 4500));
      randomEx();
      delay(random(1000, 4500));
      blinkL();
      delay(90);
      loveL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }
    void dislikeRoutine() {
      normalL();
      delay(random(1000, 7000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 6500));
      randomEx();
      delay(random(1000, 4000));
      blinkL();
      delay(90);
      angryL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }
    void hateRoutine() {
      angryL();
      delay(random(1000, 5000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 6500));
      randomEx();
      delay(random(1000, 4000));
      blinkL();
      delay(90);
      angryL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }

    void loop(void) {
      DFRobot_PAJ7620U2::eGesture_t gesture = paj.getGesture();
      if (gesture != paj.eGestureNone) {
        String description = paj.gestureDescription(gesture);  //Convert gesture number into     string description
        if (gesture == 256) {                                  //wave
          gleeL();
          delay(random(1000, 4500));
        } else if (gesture == 2 && like_score < max_like_score) {  //pet
          blinkL();
          delay(90);
          loveL();
          like_score++;
          Serial.println(like_score);
          delay(random(1000, 3000));
          if (like_score == max_like_score) {
            blinkL();
            delay(90);
            loveL();
            delay(random(1000, 3000));
          }
        } else if (gesture == 16 && like_score <= max_like_score) {  //thump
          stunL();
          like_score--;
          Serial.println(like_score);
          delay(random(1000, 4000));
          angryL();
          delay(random(1000, 3000));
        } else if (gesture == 128) {
          u8g2.clearBuffer();
          u8g2.setFont(u8g2_font_t0_11_tf);  // choose a suitable font
          dtostrf(like_score, 6, 0, buffer);
          String scoreStr = String(buffer);
          u8g2.drawStr(0, 20, scoreStr.c_str());
          u8g2.sendBuffer();
          delay(random(2000, 3500));
        }
      } else {
        if (like_score >= 11) {
          likeRoutine();
        } else if (like_score > 7 && like_score < 11) {
          kindofLikeRoutine();
        } else if (like_score > 0 && like_score < 7) {
          dislikeRoutine();
        } else if (like_score < 0) {
          hateRoutine();
        }
      }
    }

Yes, thank you.

Thank you, I will do that.

@jsotola That looked very much like an answer to the question, not a request for clarifying information. Could you please turn it into an answer? Hint: cut and paste should work. Thanks!

My code is very inefficient because of all the functions ... - not at all. Using functions to make code readable is very common, and the slowdown is minimal.

@jsotola I'm just asking that your reasonable comment about using delay() be incorporated into an answer and not a comment. However if you wish provide more code, but that wasn't what I was requesting.

The code is being slowed down by the delay() function because it is a blocking function.
The delay function does not exit until delay time passes, so no other functions can run, such as sensor reading.
The simplest solution for your code may be an FSM library (finite state machine).  It would look after all of the timing for you.
You could also replace the delay() functions with your own delay function, something like

void myDelay(int totalDelay) {

   for (i = 0; i < totalDelay/100; i++) {

                           // do some housekeeping here, like reading sensors

      delay(100);          // this blocks for only 1/10 of a second
   }                       // adjust the delay value if housekeeping takes a lot of time
}

The delay gets broken into a lot of small delays with time to do other things in between.
Another way is to check at the begining of loop() to see how much time has elapsed.
See blinkWithoutDelay example code in the Arduino IDE.
Here is an example in a simulator that may help you.
https://wokwi.com/projects/362275278547275777

Thank you! This definitely helps a lot!


text:
SB Components Micro RP2040 and ST7789 2.4 TFT LCD SPI display not working together using any library
I have a Micro RP2040 board from SB Components. Link to this product
With this I also have a 2.4 inch SPI TFT LCD screen with an ST7789 controller Link to the screen, it's on that page just scroll down
Before using the RP2040 Micro board to run this display, I decided to start by using an ESP32 Dev Module to try out the display and see how it works. This display was advertised as having an ILI9341 controller but using the Adafruit ILI9341 library I was not able to fill the full screen with the content being printed. I diagnosed and fixed this error from this thread on the Arduino Forum.
From @david_prentice's  answer in that thread I was able to figure out that my display has a ST7789 controller instead of the ILI9341 that it was advertised to have. This was a great relief as it proved that the display does work properly when used with the Adafruit ST77XX library.
I used this same library and changed the code for the pinout of the RP2040 Micro, when I connected it all up (through 10k resistors because the RP2040 board is 5V), all I get is a white screen.
Before with the ESP32 it was working perfectly and here's an image of that -

another sketch

With the RP2040 connected and turned on all I get is

My connections to the RP2040 Micro board

TFT Display Pin
RP2040 Pin

TFT_CS
GPIO 17

TFT_RST
GPIO 16

TFT_DC
GPIO 15

TFT_SDA (MOSI)
GPIO 19

TFT_SCK
GPIO 18

TFT_VCC
3.3V

LED
3.3V

TFT_GND
GND

I'm doing this pinout with all the pins except VCC and GND (cause VCC has a 3.3v that I can connect to) going through a 10k resistor to the board.
I tried with TFT_eSPI library and I wasn't even able to get it running with the ESP32... neither the RP2040 Micro board worked.
Although TFT_eSPI is the right library for RP2040 based board, it did not work..
Code I'm using for drawing the spiderweb using the ESP32 -
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>

#define TFT_DC 2
#define TFT_CS 15
#define TFT_MOSI 23
#define TFT_CLK 18
#define TFT_RST 4
#define TFT_MISO 19

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST);

void setup() {
  Serial.begin(9600);
  tft.init(240, 320);
  tft.fillScreen(ST77XX_BLACK);
  drawPattern();
}

void loop() {
}

void drawPattern() {
  int centerX = tft.width() / 2;
  int centerY = tft.height() / 2;

  for (int radius = 10; radius <= 120; radius += 10) {
    uint16_t color = (radius / 10) % 2 == 0 ? ST77XX_BLUE : ST77XX_CYAN;
    tft.drawCircle(centerX, centerY, radius, color);
  }

  for (int angle = 0; angle < 360; angle += 15) {
    float radians = angle * 3.14159 / 180;
    int x1 = centerX;
    int y1 = centerY;
    int x2 = centerX + 120 * cos(radians);
    int y2 = centerY + 120 * sin(radians);
    uint16_t color = (angle / 15) % 2 == 0 ? ST77XX_RED : ST77XX_YELLOW;
    tft.drawLine(x1, y1, x2, y2, color);
  }

  tft.fillCircle(centerX, centerY, 10, ST77XX_GREEN);
}

This worked with the ESP32 but when I changed the pin numbers so that I could connect it to the RP2040 Micro board it did not work with the RP2040.
Also with the ESP32, all the colors are inverted, but that's another issue I can fix myself.

what exactly should the resistor do?

@Juraj I heard you can connect the data pins (they are 3.3v logic) to 5v boards by using resistors as voltage level shifters if you don't have that circuitry in the display itself

that is wrong. but RP2040 is a 3.3 V MCU. how do you have 5 V pin on a RP2040 board?

@Juraj Just tried it without the resistors, same issues. I thought this board was having 5V logic because it has a 5V power output too (like the arduino UNO.. 5V logic but has a 3.3V output too)


text:
my LED light strip wont turn off
/*
 * when its bright the lights will turn off
 * when its dark the lights will glow blue and green
 * when it is in between, the lights will turn red
 */

 #include <Adafruit_NeoPixel.h>
 #ifdef _AVR_
 #include <avr/power.h> //reduired for 16 MHz adafruit trinket
 #endif

 //which pin on arduino is connected to the neo pixels?
 #define PIN            7
 //how many neoPixels are attached to the arduino
 #define NUMPIXELS 10 //popular NeoPixel ring size

 //when setting up the neoPixel library, we tell it how many pixels, and which pin to use to send signals.
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

 int photoPin = A0;
 int pin7 = 7;

 void setup(){
  Serial.begin(9600); //turn on the serial monitor
  pixels.begin(); //INTIALIZE NeoPixel strip object (REQUIRED)
 }

void loop(){
  pixels.clear(); //set all pixels colors to 'off'
  int lightRaw = analogRead (photoPin); //get the readingfrom the photoPin and put it in a new cariable called lightRaw
  int light = map(lightRaw, 1023, 0, 10, 0); //take the lightEaw variable and convert it to a value from 0 to 10.

  Serial.println("the current light level is:"); //display this message on the serial montior
  Serial.println(light); //desplay the light variable on the serial monitor

  if(light <4){
    //pixels.color() takes RGB values, from 0,0,0 up to 255,255,255
    pixels.clear(); //set all picel colors to 'off'
    pixels.setPixelColor(0, pixels.Color(255, 252, 222));
    pixels.setPixelColor(1, pixels.Color(255, 252, 222));
    pixels.setPixelColor(1, pixels.Color(255, 252, 222));
    pixels.setPixelColor(3, pixels.Color(255, 252, 222));
    pixels.setPixelColor(4, pixels.Color(255, 252, 222));
    pixels.setPixelColor(5, pixels.Color(255, 252, 222));
    pixels.setPixelColor(6, pixels.Color(255, 252, 222));
    pixels.setPixelColor(7, pixels.Color(255, 252, 222));
    pixels.setPixelColor(8, pixels.Color(255, 252, 222));
    pixels.setPixelColor(9, pixels.Color(255, 252, 222));
    pixels.show();    //send the updated pixel colors to the hardware
  }

    else if(light <2){
      //pixels.color() takes RGB values, from 0,0,0 up to 255,255,255
        pixels.clear(); //set all picel colors to 'off'
      pixels.setPixelColor(0, pixels.Color(0, 0, 0));
    pixels.setPixelColor(1, pixels.Color(0, 0, 0));
    pixels.setPixelColor(1, pixels.Color(0, 0, 0));
    pixels.setPixelColor(3, pixels.Color(0, 0, 0));
    pixels.setPixelColor(4, pixels.Color(0, 0, 0));
    pixels.setPixelColor(5, pixels.Color(0, 0, 0));
    pixels.setPixelColor(6, pixels.Color(0, 0, 0));
    pixels.setPixelColor(7, pixels.Color(0, 0, 0));
    pixels.setPixelColor(8, pixels.Color(0, 0, 0));
    pixels.setPixelColor(9, pixels.Color(0, 0, 0));
    pixels.show();    //send the updated pixel colors to the hardware
    }

    else{
      pixels.clear(); //set all pixel color to 'off'
      pixels.show(); //send the updated pixel colors to the hardware.
    }
      delay(1000); //a small delay so the program isn't checking ever millisecond.
    }

what is your specific question? ... please add a focused, answerable question to your post

reduce your code to the simplest program that turns on one LED for one second, turns off for one second, and then repeats

This is pointless else if(light <2) following if(light <4) because it will never be executed. You probably want to swap the conditions for the case that light is between 2 and 4. It may not be your main problem though.

Come on, @jsotola, the subject line makes it clear that the LEDs do not turn off, and looking at the code it is obvious why. If you don't want to take the trouble to look at the post, don't bother commenting. The question is "why do my LEDs not turn off?" but not expressed in those exact words.

@NickGammon the question could also be how do I debug this?

if(light <4){
   // do something
  }

else if(light <2){
  // do something else
  }

else{
    // do another thing
    }

If light is low (eg. 1) then that will pass the first test and the other two tests don't do anything. After all, 1 is less than 4 and also less than 2.
You need to rethink the way you are doing your tests, possibly changing "less than" to "greater than" which would make more sense.

There may be more to it than that. The code in the final else block will execute when light >= 4. That code would appear to be designed to switch the lights off. Of course, it may be that the OP has not tested under these conditions and thus never seen the lights go off. It could also be that the code is faulty. Hence the note of caution in my comment above.

You would need to move stuff around. If the light > 4 then turn the lights off, if > 2 then show blue and green, otherwise show red.


text:
Invalid use of void expression (how to use function pointer with input)
I'm defining an attachinterrupt and I'm running into an error. The line in question is:
void setup() {
   attachInterrupt(digitalPinToInterrupt(stallsense1), changedirection(1), RISING);
   attachInterrupt(digitalPinToInterrupt(stallsense2), changedirection(2), RISING);
}

and the error I'm getting is:
error: invalid use of void expression
attachInterrupt(digitalPinToInterrupt(stallsense2), changedirection(2), RISING);
                                                                                ^
exit status 1
invalid use of void expression

The idea is I have one function changedirection and two possible inputs, either 1 or 2.
I believe the issue is where I've called the function changedirection(1). I want to simply tell attachinterrupt to call the function changedirection with an input of either 1 or 2. How would I do this?

attachInterrupt expects a simple pointer to function taking no arguments and returning nothing (void).
So, really there's no way to directly do what you're talking about.  There's no currying ability builtin.  You can define your own functions like
void proxy_changedirection_1() {
    changedirection(1);
}

And then attachInterrupt specifying proxy_changedirection_1, or you can use a lambda with no captures for the same purpose:
attachInterrupt(
    digitalPinToInterrupt(stallsense1),
    [] () {
        changedirection(1);
    },
    RISING
);

Thank you very much. The lambda notation is closer to what I had envisioned coming from python.

What happened is you wrote a void expression where an expression of type 'pointer to function of void returning void' (i.e., no arguments and no return value), was expected. The name of a function with no parentheses for an argument list is an expression of type 'pointer to function' taking whatever arguments & types that named function was declared to expect, and returning whatever type that named function was declared to return.
But if you write the parentheses with it, now you've written an expression that 1) would (if it were valid) get evaluated during the call to attachInterrupt() - much earlier that you want it to be! - and return a value of that return type rather than the type you expected.
@timemage has offered two ways to solve this.


text:
Don't understand problem with my code
I'm trying to get a robot car(elegoo one) to do the obstacle avoidance course. I am trying to write my own one from scratch to better myself and thus would really appreciate it if someone were to tell me what's wrong with my code and why it's not working
#include <Servo.h>  //servo library
Servo myservo;      // create servo object to control servo
Servo servosweep;
int Echo = A4;
int Trig = A5;

#define ENA 5
#define ENB 6
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11
#define carSpeedForward 100
#define carSpeedLeftandRight 150
int rightDistance = 0, leftDistance = 0, middleDistance = 0;
int pos=0;

void forward(){
  analogWrite(ENA, carSpeedForward);
  analogWrite(ENB, carSpeedForward);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println("Forward");
}

void back() {
  analogWrite(ENA, carSpeedForward);
  analogWrite(ENB, carSpeedForward);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println("Back");
}

void left() {
  analogWrite(ENA, carSpeedLeftandRight);
  analogWrite(ENB, carSpeedLeftandRight);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println("Left");
}

void right() {
  analogWrite(ENA, carSpeedLeftandRight);
  analogWrite(ENB, carSpeedLeftandRight);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println("Right");
}

void stop() {
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
  Serial.println("Stop!");
}

//Ultrasonic distance measurement Sub function
int Distance_test() {
  digitalWrite(Trig, LOW);
  delayMicroseconds(2);
  digitalWrite(Trig, HIGH);
  delayMicroseconds(20);
  digitalWrite(Trig, LOW);
  float Fdistance = pulseIn(Echo, HIGH);
  Fdistance= Fdistance / 58;
  return (int)Fdistance;
}

void setup() {
  myservo.write(pos);
  myservo.attach(3);  // attach servo on pin 3 to servo object
  Serial.begin(9600);
  pinMode(Echo, INPUT);
  pinMode(Trig, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  //stop();
}

void loop(){
  for (pos = 0; pos < 90; pos += 1.0) {
  servosweep.write(pos);
  delay(50);
  leftDistance=Distance_test();
  }

  myservo.write(90);
  middleDistance=Distance_test();

  for (pos=90;pos<=180;pos+=1.0){
    servosweep.write(pos);
    delay(50);
    rightDistance=Distance_test();

  }

  if(rightDistance > leftDistance) {
        right();
        delay(360);
      }
      else if(rightDistance < leftDistance) {
        left();
        delay(360);
      }
      else if((rightDistance <= 40) || (leftDistance <= 40)) {
        back();
        delay(180);
      }
      else {
        forward();
      }
}

I'm trying to get the ultrasonic sensor to read values from the left(0 to 90), the middle(90) and the right(90 to 180) and then use them for comparison to decide where to go. When I run this code my car goes in circles and I don't know what the problem is. Any help would be appreciated.

you don't need the two for loops .... leftDistance is only measured at 90 degrees ... rightDistance is only measured at 180 degrees

As a couple people already pointed out, you're using for loops that are unnecessary, and will cause you to get the wrong measurements. You're better off just using myservo.write(); to set your servo to positions 0 and 180.
Additionally you never check to see if there's an obstacle infront of your robot. Instead, your robot immediately tries turn right or left. That's what's causing it to spin.
Here's a fixed version of your void loop()
void loop(){

  myservo.write(0);
  delay(50);
  leftDistance=Distance_test();

  myservo.write(90);
  delay(50);
  middleDistance=Distance_test();

  myservo.write(180);
  delay(50);
  rightDistance=Distance_test();

  /* Start by checking if there is space to go forward */
  if(middleDistance > 40){
     forward();
     }
/* If there isn't space to go forward, turn */
  else if(rightDistance > leftDistance) {
        right();
        delay(360);
      }
  else if(rightDistance < leftDistance) {
        left();
        delay(360);
      }
  else if((rightDistance <= 40) || (leftDistance <= 40)) {
        back();
        delay(180);
      }
   else {
        forward();
      }
}

I hope this helps!

As jsotola writes, you are running through the 0-89 position and updating leftDistance every time. Then you find the middleDistance and finally you go through 91-180 and update rightDistance. After the two for loops, leftDistance will have the value for 89 and rightDistance will have the value for 180 because you overwrite your value without doing anything with it.
Start by skipping the for loops and measure at 0, 90 and 180 and use these values as you left, middle and right distance. When deciding if you want to back up, use the middle distance. Remember to use a delay between measurements that is large enough for the servo to get to the position for the next measurement


text:
problem controlling rgb led with one button
I'm trying to make a lamp which quality to change color by pressing a
button, pressing once turns on red, pressing again turns on blue and so on, but I also want it to have a light effect in which it smoothly switches between different colors, my code does, however when pressing the button and getting to the last function and keep pressing the button no longer does the light change, it just stays in that state, I have been trying to solve it and investigating for hours but I do not get the expected result, I hope you can help me, thanks.
I enclose the wiring diagram and the code used.

#define varfija 0

int ledR = 11;
int ledB = 10;
int ledG = 9;
int pinButton = 7;
int buttonValue;
int count = 0;
int brillo;
int button_old = 0;

void setup() {
    pinMode(ledR, OUTPUT);
    pinMode(ledG, OUTPUT);
    pinMode(ledB, OUTPUT);
    pinMode(pinButton, INPUT);
}

void loop() {
    buttonValue = digitalRead(pinButton);
    if (button_old == 0 && buttonValue == 1) {
        count++;
        button_old = 1;
    }
    if (button_old == 1 && buttonValue == 0)
        button_old = 0;
    if (count > 4)
        count = 0;

    if (count == 0) {
        analogWrite(ledR, 0);
        analogWrite(ledG, 0);
        analogWrite(ledB, 0);
    }
    else if (count == 1) {
        analogWrite(ledR, 255);
        analogWrite(ledG, 0);
        analogWrite(ledB, 0);
    }
    else if (count == 2) {
        analogWrite(ledR, 0);
        analogWrite(ledG, 255);
        analogWrite(ledB, 0);
    }
    else if (count == 3) {
        analogWrite(ledR, 0);
        analogWrite(ledG, 0);
        analogWrite(ledB, 0);
    }
    else if (count == 4) {
        for (int i = 1; i < 255; i++) {
            analogWrite(ledR, i);
            analogWrite(ledB, varfija);
            analogWrite(ledG, varfija);
            delay(5);
        }
        for (int i = 255; i > 0; i--) {
            analogWrite(ledR, varfija);
            analogWrite(ledB, i);
            analogWrite(ledG, varfija);
            delay(5);
        }
        for (int i = 0; i < 255; i++) {
            analogWrite(ledR, varfija);
            analogWrite(ledB, varfija);
            analogWrite(ledG, i);
            delay(5);
        }
    }
}

sorry for my english, I don't master it

Do a Web search for “Arduino debounce button”.

It takes a 32555 milliseconds between button checks in state 4 (every 3.825s) so you have to hold it for some time and then it might get noticed...

You want to check the button, but at the same time run the animation that takes around 4 seconds. To combine these you'd have to change the animation code, so it no longer uses any delays. So it's no longer blocking the button code. But for example uses the time (millis) to determine the values or the red green and blue led. A simpler version of this problem is Blink without delay.

I posted an answer to a very similar question recently: https://arduino.stackexchange.com/questions/76084/rgb-led-and-a-push-button-in-tinkercad/76097#76097 Note how that code uses millis to debounce the button presses. You'll have to do something similar to get the LED color to change over time. I suggest a simple state machine where you have states for the different colors plus states for transitions between colors.


text:
What Arduino boards would be compatible?
I am considering using an arduino over the raspberry pi for a new project. However, I am not sure what arduino I should buy so that it is compatible with the below add-on.

Are all Arduinos compatible?
TIA.
Edit:
Link to product- https://www.adafruit.com/product/3387
My goal is to use an arduino with the above product to move a 3D model in Unity 3D.

Potentially all are compatible, but it is hard to tell as you did not include any of the technical details. Can you update your question with the technical details and or a link to the product? Compatible is a big word, there are many aspects to it including voltage, signaling and software support on your Arduino of choice.

Of course, my bad. Editing now!

As one can see from the pinout description page (https://learn.adafruit.com/adafruit-lsm9ds1-accelerometer-plus-gyro-plus-magnetometer-9-dof-breakout/pinouts):

So this board is literally designed to be powered by 3.3V and 5V and have compatible logic levels for both these voltage ranges, which is what every Arduino known to me and the Raspberry Pi use.
Furthermore, there is also Arduino Code (https://github.com/adafruit/Adafruit_LSM9DS1)  which is compatible with pretty much every Arduino Core and Raspberry Pi Python code (https://learn.adafruit.com/adafruit-lsm9ds1-accelerometer-plus-gyro-plus-magnetometer-9-dof-breakout/python-circuitpython).
So by means of voltage levels and platforms, this board is highly compatible with everything out there that is either 3.3V or 5V powered and has a SPI or I2C peripheral.

Right. Which is to say pretty much every Arduino out there. If it has hardware I2C lines, it will work with that board, whether the Arduino is 3.3V or 5V. Note that most commonly used Arduinos and their accessories are 5V, so I'd recommend going with a 5V module for compatibility with other "shields" and accessories.


text:
Control speed of a dc motor with a 9v battery
Problem:
I want to have a 9v battery that powers a dc motor. I want to control it with a bluetooth remote that has 3 buttons. 1st button is turn the motor with 1.5v, 2nd button is motor off and the 3rd button is full power (9v). Here is the problem normally I will change volt with my arduino using code, but it has a max voltage of 3.6v so I can't control the battery with the arduino. Also I would like the 9v battery to power the arduino and bluetooth module if that is possible, so I have only one battery that powers everything.
What I tried:
I found a lot of different things on the internet. Pwm, Tip120 transistor, L298N and it only confuses me more I have no idea where to start. Spend 8 hours looking for stuff and no step further.
Result:
I hope everything will work with a 9v battery and the bluetooth remote can switch between 3 different speeds.![enter image description here]

Too broad and off-topic, but I suggest you read about pulse-width modulation (PWM) control of DC motors, as well as the power requirements of your DC motor.  Often alkaline 9 V battery won't cut it, try lithium batteries instead.

You have 3 problems here:

Driver circuit the motor: Since you only want to control the motors speed (not changing it's direction, where you would need a H-bridge like the L298N), a very simply driver circuit is sufficient. It can consist of a bipolar transistor or a MOSFET. The Arduino's digital output pin would set the transistor/MOSFET to conductive or non-conductive, which turns the motor on or off. The motor is connected (through the transistor/MOSFET) with the full supply voltage. For the needed circuit, you can google terms like "transistor as switch" or "MOSFET as switch". That should give you plenty of tutorials.
Controlling the motor speed: Normally the speed of a motor is not controlled through the voltage, since the speed behaves not linear with the voltage. Instead we use PWM (Pulse Width Modulation), where a squarewave voltage with a constant frequency is outputted at the Arduino's pin. To change the motor speed, you change the ratio between ON and OFF time of the pin (called "duty cycle"). So the motor basically get's turned on and off very fast. Since the motor is to slow, to follow the fast change, we are basically giving it small pushes very fast. If you only push half of the time (duty cycle 50%), the motor will run with about half the speed. In Arduino code you use analogWrite(pin_number, x) with x between 0 and 255 to output a PWM wave at the specified pin. Refer to the Arduino documentation for details.
Powering the whole device: First: A 9V block battery is actually like the worst choice for most cases (especially for devices with motors). It has a big series resistance, what means, that it cannot provide much current without dropping the voltage radically. They are meant for low-current devices. Better use multiple AA/AAA batteries in series.
You didn't state, what Arduino you actually use, but from the description, it has to be one of the 3.3V boards, like the Arduino Pro Mini 3.3V version. Most Arduino boards also have a small voltage regulator on them. The input for it is mostly marked with Vin. Please refer to the documentation of your Arduino board, to check, which voltages are suitable for that voltage regulator. If you don't have a voltage regulator on your Arduino or your battery voltage doesn't fit, you have to provide the power through your own external voltage regulator. You should use a switching regulator (far more efficient, than linear regulators), which can provide the needed power (depending on the Arduino and the bluetooth device maybe between 50mA and 300mA, difficult to say generally) plus a bit overhead.
You should then provide the motor with the full battery voltage, especially not through the Arduino's voltage regulator. Motors can draw quite much current. If you draw more current through a regulator, than possible, it will overheat, emergency shutdown or even burn out. If the battery voltage is not suitable, you should use a voltage regulator, that can safely provide the needed current.

Note: Depending on the size of the motor and it's load, you might want to add a flyback diode, that would safely let inductive reverse currents flow to ground, so that the inductive voltage is not piling up in the transistor/MOSFET.

Thank you so much! Finally I understand it! I will try this and let you know if it works! :)

Again Thank you, almost everything works! Only thing I don't know is how I can add the diode against the back voltage. I made picture of the diagram that I use and I am not sure if its correct. And I made a picture of the project I am working on.(I post them with the orginal message.) I am not sure if i wired it correctly because my esp gets data from the com3 when the motor is turned(I think it's because of the back voltage). Also this way the diode became extremly hot.

The diode is in the wring place. Currently all the motor current is flowing through it, so it gets hot. The flyback diode should bridge source and drain of the mosfet in the reverse direction, so that in normal operation it is blocking, leaving the operational function to the MOSFET. When the motor gets stopped suddenly, a negative voltage will build up at the MOSFET. The diode will then connect this voltage to ground, so that the voltage dissipates there and cannot ruin the MOSFET

I don't know, what you mean by com3, but this seems due to the motors noise. Shielding from noise can be a complex thing, too complex for this answer. Google about it, to find some fitting measures.

I made a picture again of my setup and also a diagram of the mosfet and it's connections. Is this what you meant? When I tried this I still get a blinking yellow light on my esp8266. (back voltage that probably gets in the board) Also I need to disconnect and reconnect my esp8266 otherwise it won't process any code. Can you see something I am doing wrong? It's a 1n4001 diode and I use PWM, does that make a problem? Thank you in advance!


text:
Dc motor backvoltage, how to place the diode correctly?
My previous questions have been anwsered, so thank you all for that!
I make a new question post because I have some other problems with my setup. I use a esp12s 8266 chip. It sends a PWM signal to a n-channel mosfet, so I can regulate the speed of the dc motor that is attached to the drain of the mosfet. The DC motor has extra power from a 9v battery and this battery negative is connected to the GND of the 8266. I can control it with bluetooth hc-05 module, it has 3 options, 40%, 0% (off) and 100% (full power).
Here's the problem:
I can control everything and it seems like it works all fine, but when the motor starts spinning I see a yellow led flashing on my 8266 chip and I can't control it anymore. I read about backvoltage from the motor. So I think maybe the backvoltage is causing the chip not to function anymore. To make it work again I need to disconnect and reconnect the chip for it to work again.
So my question is: could this be the backvoltage or something else?
And if it's the backvoltage how do I need to connect the diode (1n4001) in this circuit?
I read when a motor stops then the backvoltage happens, but in my case the led on the 8266 starts flashing when it spins. So maybe I hooked something the wrong way. here I have some pictures of the different setups I tried.
Of course I will solder everything nicely, but for now it's just to get a quick impression of the hookup.
Hopefully someone can help me out, thanks in advance!

More likely your weak 9v battery is unable to supply enough power.

I read when a motor stops then the backvoltage happens,

That is not true. With a brushed DC motor the back-EMF ("backvoltage") occurs at least twice (often more, depending on the number of commutator segments) per revolution of the motor.  Brushed DC motors are very noisy.
While you can use a diode (connected as you would for a relay) it's not the best solution.  Instead you really need a proper EMI-absorbing circuit.
This consists of three capacitors - all very small values, in the range 1-10nF, which connect all parts of the motor together and bleed off any induced voltages safely.
The first capacitor connects directly across the terminals.  This will safely remove the back-EMF created in the windings as the voltages switch back and forth due to the rotation of the commutator.
The other two capacitors each connect from one terminal to the metal housing of the motor (one to each side of the housing).  This will safely couple the housing to the rest of the circuit and cause it to act as a shield containing the magnetic fields better within the motor.

Thank you. I will try this out and let you know if it worked! I also added another picture that I found on the internet. On the picture you see between the negatief en positive of the motor there is a little capacitor 1uF ceramic capaciter. So you say I need to connect it like that right? and also one on the negative to the housing and the positive to the otherside of the housing, right? :)

Yes, that's right.  The housing-connected ones are less important than the one across the terminals, but still recommended if you can.

Thank you! I don't have the blinking Led on the 8266 and no data noise!

You're looking for something called a "flyback diode."
What happens is, during "normal use" (when the DC motor is being powered by the system), you have a DC motor.  But, when the system stops giving input, and the DC motor "spins down," it can become a power generator -- generators and motors are actually very much the same, it just depends on if they're generating the power, or using the power.
The idea with the flyback diode is that it doesn't let that generated current "back" into the system, and burn up your MCU.  I've seen them in series with a small resistance, to help quickly bleed off any current/voltage the DC motor ends up generating.  With it in series, the diode stops any power from being "wasted," as current will never flow "backwards" through the diode, and thus the resistor.
When you "cut the power" to the DC motor, current can then flow through the "mini-loop" and decay through the resistor (which is not pictured in this example).

Thank you, it gave me a better understanding of a dc motor!

Okay, I'm not sure what you're trying to accomplish, electrically, but the diagram you added doesn't make sense.  It also doesn't match any of the pictures you've posted.  In the diagram, you have your emitter and collector tied together with a diode... but your pictures don't have ANYTHING attached to your emitter leg... you have things "wrapped" around your heatsink/ground, for some reason?
So we'll ignore the pictures that don't make actual circuits, and focus on your diagram.  In the diagram, you've accomplished this:

If you look at this, the diode is doing nothing -- your BJT already has Miller resistance between the emitter and collector, so the diode does nothing for you, here.  You also don't need any capacitors, as you are not looking to store any power, for any reason.  Because of this, I've changed it to a resistor (R4).
What you're really looking for is something more along these lines:

With this, your 9V battery will only power the motor when the BJT is on (your Pin10 is HIGH).  This completes the circuit, and current flows through your motor.  The diode (D1) prevents any current from flowing through the resistor (R2), and no power is lost.
When you turn your motor "off" by setting Pin10 to LOW, kinetic energy will cause your motor to "continue spinning" a little bit -- it's not going to just stop dead, since that energy needs to go somewhere.  This little bit of remaining spin turns your DC motor into a DC generator, and it provides its own power.  This current/voltage needs to go somewhere, or you'll burn things up.
This is where the diode (D1) and resistor (R2) come in handy.  That current can now flow through the mini-loop, and bleed-off this induced power -- or flyback voltage spike -- which is why it's called a "flyback diode."  You're trying to bleed-off that power, not store them, so you need a resistor instead of a capacitor.
So lose the caps, substitute with a resistor, and move your flyback diode.

I am sorry I was not clear about the diagram, I don't use the diagram. I only wanted to point out that the guy from the diagram used a capacitor. So I am not using a BJT but a mosfet. I don't know if that makes a big differents. Also I can't read a circuit diagram, well only the very basic ones. So I didn't really understand what you mean only a small portion of it. I will first try the capacitor and if it not works I can always dive deeper in your story, so thanks!

@Bart BJT's and MOSFETS are both transistors, one is a voltage-controlled voltage source, the other is a current-controlled current source -- Either way, you're connecting to the heatsink (the big plate) and not the collector.  You're not making a complete circuit in either of your pictures.  I would recommend you understand how basic transistors (BJT's and MOSFETS) work before you try to wire them up -- you have not made any complete circuits, and I'm surprised your motor is spinning at all.

I followed a part of this video https://www.youtube.com/watch?v=T9Zpir5hidw&t=100s