0

I have an Arduino project to control a motor's speed at 3 levels, indicated by 3 LEDs, so level 1 is speed 1 and LED 1, and so on for levels 2/3.

Also, I added a low-battery voltage indicator to monitor the battery level.

I am going to use an ATtiny45, which has 8 pins(Vcc, GND, 1 analog pin, 5 digital pins). The project needs 6 digital pins and 1 analog pin, so only one more pin is needed.

I do not want to use an expander or I2C, as they will make the project more complex, and it is only one pin!

I can use a larger microcontroller but it would be the last choice.

Here is my project's diagram and code:

enter image description here

//********************************************^************************************************
//  https://forum.arduino.cc/t/control-motor-speed-with-npn-and-push-button-no-driver/1184925
//
//
//
//  Version    YY/MM/DD    Comments
//  =======    ========    ====================================================================
//  1.00       20/23/02    Running code
//  1.10       20/23/03    Added motor and LEDs OFF if switch pressed for >= 3 sec.
//
//
//

#define PRESSED            HIGH
#define RELEASED           LOW

#define ENABLED            true
#define DISABLED           false

#define LEDon              HIGH
#define LEDoff             LOW

#define MOTORoff           0

#define lipo               A0

float lipoV = 0;

//GPIOs
const byte Button        = 2;
const byte ledpin        = 3;
const byte ledpin1       = 4;
const byte ledpin2       = 5;
const byte Motor         = 9;
const byte heartbeatLED  = 13;
const byte Red           = 6;

//Variables
byte lastButton          = RELEASED;
byte currSwitch;

int Speed_Level;

bool bCheckingSwitch     = DISABLED;

//timing stuff
unsigned long heartbeatTime;
unsigned long switchesTime;
unsigned long threeSecondTime;

//                                      s e t u p ( )
//********************************************^************************************************
void setup()
{
  pinMode(Button, INPUT);
  pinMode(lipo, INPUT);

  pinMode(ledpin, OUTPUT);
  pinMode(ledpin1, OUTPUT);
  pinMode(ledpin2, OUTPUT);
  pinMode(Motor, OUTPUT);
  pinMode(heartbeatLED, OUTPUT);
  pinMode(Red, OUTPUT);
  

} //END of   setup()


//                                       l o o p ( )
//********************************************^************************************************
void loop()
{

  //************************************************              T I M E R  heartbeatLED

  //is it time to toggle the heartbeat LED ?
  if (millis() - heartbeatTime >= 500ul)
  {

    //restart this TIMER
    heartbeatTime = millis();

    //toggle the heartbeat LED
    if (digitalRead(heartbeatLED) == HIGH) digitalWrite(heartbeatLED, LOW);
    else digitalWrite(heartbeatLED, HIGH);
  }

  //************************************************              T I M E R  check switches
  //is it time to check our switches ?
  if (millis() - switchesTime >= 50ul)
  {
    //restart this TIMER
    switchesTime = millis();

    checkSwitches();
  }

  //************************************************              T I M E R  three seconds
  //if enabled, is it time to turn things OFF ?
  if (bCheckingSwitch == ENABLED && millis() - threeSecondTime >= 2000ul)
  {
    //we are finished with this TIMER
    bCheckingSwitch = DISABLED;

    //restart the sequence
    Speed_Level = -1;

    analogWrite(Motor, MOTORoff);
    digitalWrite(ledpin, LEDoff);
    digitalWrite(ledpin1, LEDoff);
    digitalWrite(ledpin2, LEDoff);
    digitalWrite(Red, LEDoff);
  }

} //END of   loop()


//                               c h e c k S w i t c h e s ( )
//********************************************^************************************************
void checkSwitches()
{
  byte state;

  //************************************************              Button
  state = digitalRead(Button);

  //has there been a state change in the switch ?
  if (lastButton != state)
  {
    //update to the new state
    lastButton = state;

    //*******************************
    if (state == PRESSED)
    {
      //enable the TIMER
      bCheckingSwitch = ENABLED;

      //start the TIMER
      threeSecondTime = millis();
    }

    //*******************
    //the switch was released
    else
    {
      //disable the TIMER
      bCheckingSwitch = DISABLED;

      Speed_Level++;
      lipoV = analogRead(lipo);

      //battery checker
      if(lipoV < 680){
        digitalWrite(Red,LEDon);
      }

       else
       {
        digitalWrite(Red,LEDoff);
    
       }

      //don't go over 3
      if (Speed_Level >= 4)
      {
        Speed_Level = 0;
      }

      //*******************
      if (Speed_Level == 1)
      {
        analogWrite(Motor, 50);
        digitalWrite(ledpin, LEDon);
        digitalWrite(ledpin1, LEDoff);
        digitalWrite(ledpin2, LEDoff);
      }

      //*******************
      else if (Speed_Level == 2)
      {
        analogWrite(Motor, 75);
        digitalWrite(ledpin, LEDoff);
        digitalWrite(ledpin1, LEDon);
        digitalWrite(ledpin2, LEDoff);
      }

      //*******************
      else if (Speed_Level == 3)
      {
        analogWrite(Motor, 100);
        digitalWrite(ledpin, LEDoff);
        digitalWrite(ledpin1, LEDoff);
        digitalWrite(ledpin2, LEDon);
      }

      //*******************
      else
      {
        analogWrite(Motor, MOTORoff);
        digitalWrite(ledpin, LEDoff);
        digitalWrite(ledpin1, LEDoff);
        digitalWrite(ledpin2, LEDoff);
        digitalWrite(Red,LEDoff);
      }

  }

}
}//END of   checkSwitches()

//********************************************^************************************************

Can I use tA0 as input and output at the same time like this?

enter image description here

Or can I reduce the LED pins, meaning use 1 pins for 2 LEDs?

8
  • You can combine your button and an LED by switching it in loop between input, reading it, then back to output. As long as you do that 50+ times a second the LED will look normal, and the button will block out the LED, providing visual feedback as a bonus.
    – dandavis
    Commented Nov 6, 2023 at 22:50
  • 1
    @dandavis can you please give an example
    – Tito
    Commented Nov 6, 2023 at 23:08
  • Actually, thinking about it more, I would just replace your 3 status LEDs with neopixels, and drive all three+ from one pin. To combine, you take a 1k from 5v to the LED then ground. Button is parallel to the LED. LED on and off is just digitalWrite(x,1), to read button pinMode(x, INPUT);st=digitalRead(x);pinMode(x, OUTPUT); to switch back to LED viewing.
    – dandavis
    Commented Nov 6, 2023 at 23:11
  • This will be much complex in coding i think
    – Tito
    Commented Nov 6, 2023 at 23:14
  • 1
    @dandavis sorry did not catch you, i think my code and led setup have exactly what you are saying, leds are connect 1k to 5v then gnd as in my diagram and the code you said is in my sketch code!
    – Tito
    Commented Nov 7, 2023 at 2:35

2 Answers 2

4

As a (slightly hacky and binary :) ) suggestion, you could use just two LEDs and free up a pin with the following...

Level 1 - LED 1 on, LED 2 off

Level 2 - LED 1 off, LED 2 on

Level 3 - LED 1 on, LED 2 on

This is a really simple change to your current set up and code

Alternatively (as suggested by @dandavis) use a set of 3 neopixels and drive from just 1 pin

1
  • simple and easy, that what i wanted
    – Tito
    Commented Nov 7, 2023 at 17:09
2

You may try charlieplexing your LEDs. Using only 3 digital pins you can drive up to 6 LEDs. A web search for “charlieplexing Arduino” should get you started.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.