analogRead, Servo conflict on digispark

I am new to Arduino and the DigiSpark board. I was trying to control a servo from a pot and an running into a problem. I can control the LED with the analogRead of A1 but when I enable that line of code, the servo no longer operates even though I am setting the value of "angle" This code will not run the servo.

#include <SimpleServo.h>

SimpleServo ServoTest;

void setup() {
  // put your setup code here, to run once
 // Serial.begin(9600);
  ServoTest.attach(0);
  pinMode(1,OUTPUT);
  analogReference(INTERNAL2V56);
}

void loop() {
// put your main code here, to run repeatedly:
int angle = map(analogRead(A1), 0, 1023, 0, 180);
//int angle = 127;
analogWrite(1,angle);

angle =0;
ServoTest.write(angle);
delay (500);
angle=45;
ServoTest.write(angle);
delay (500);
angle=90;
ServoTest.write(angle);
delay (500);
angle=135;
ServoTest.write(angle);
delay (500);
angle=180;
ServoTest.write(angle);
delay (500); 


}

However, if I comment out the analogRead, as below, the servo does operate.

#include <SimpleServo.h>

SimpleServo ServoTest;

void setup() {
  // put your setup code here, to run once
 // Serial.begin(9600);
  ServoTest.attach(0);
  pinMode(1,OUTPUT);
  analogReference(INTERNAL2V56);
}

void loop() {
// put your main code here, to run repeatedly:
//int angle = map(analogRead(A1), 0, 1023, 0, 180);
int angle = 127;
analogWrite(1,angle);

angle =0;
ServoTest.write(angle);
delay (500);
angle=45;
ServoTest.write(angle);
delay (500);
angle=90;
ServoTest.write(angle);
delay (500);
angle=135;
ServoTest.write(angle);
delay (500);
angle=180;
ServoTest.write(angle);
delay (500); 


}

Any ideas why this might be? I've tried adding some long delays after the analogRead and that doesn't seem to help.

Thanks for any help you can provide.

Are you using the following board?


Figure-1:

Or


Figure-2:

1 Like

I am using the board from Figure 1. The servo is connected to P0, the onboard LED to P1, and the servo to P2 (A1). When I make the analogRead statement active, I am able to read the A/D value on the pot and control the brightness of the onboard LED with an analogWrite on P1.

How it behaves if you detach the servo before analogRead and re-attach after?
ServoTest.detach(0);

Is this required by the DigiSpark?

Hi! Welcome to the Forum.

The library documentation states that:

"The program can't do anything else while the servo is being signaled"

It's not a good sign...

Maybe change the library helps. Google search in other discussions shows other 2 possibilities: PrecisionServo.h and SoftwareServo.h

No, it is not needed. I believe it defaults to the power supply voltage if you don't specify an internal reference.

Are you using SG90 Servo Motor?

I do not understand why I can not use PB2 to read an analog pin, so I use A1 to read a pot then move the servo on PWM PB0.

// https://cdn.sparkfun.com/assets/2/8/b/a/a/Tiny_QuickRef_v2_2.pdf

int servo = PB0;      // pwm
int pot   = PB2;      // ain
#define angle0    450 // servo at 0 degrees
#define angle180 2450 // servo at 180 degrees

void setup() {
  pinMode(servo, OUTPUT);
  pinMode(pot, INPUT);
}

void loop() {
  readPot();
}

void readPot() {
  int i = map(analogRead(A1), 0, 1023, angle0, angle180);
  // int i = map(analogRead(pot), 0, 1023, angle0, angle180);
  gotoAngle(i);
}

void gotoAngle(int angle) {
  digitalWrite(servo, HIGH);
  delayMicroseconds(angle);
  digitalWrite(servo, LOW);
  delayMicroseconds(angle180 - angle);
}

Which ATTiny Core are you using?

Thanks. I will look into these libraries.

ATTiny85

I had some old servos from an RC plane and am using one of them. It is an Airtronics 94102.

Didn't have any effect?

Didn't try detach, but I will and will report back.

I found some information on non-blocking analog reads and implemented that in the code instead of analogRead. Everything seems to be working okay.

#include <SimpleServo.h>

SimpleServo ServoTest;
volatile int analogValue = 0;  // Stores ADC result
volatile bool adcReady = false; // Flag to indicate a new value is available


void setup() {
  // put your setup code here, to run once
 // Serial.begin(9600);
  ServoTest.attach(0);
  pinMode(1,OUTPUT);
  analogReference(INTERNAL2V56);
  pinMode(2, INPUT); // Set P2 (A1) as input
  Serial.begin(9600);
  startADC();  // Start first ADC conversion
}

void loop() {
  // put your main code here, to run repeatedly:
 // int LED=0;
 //LED = analogRead(A1);
int angle = map(analogValue, 0, 1023, 0, 180);
//int angle=analogRead(A1);
    if (adcReady){
        adcReady = false;  // Reset flag
        Serial.println(analogValue); // Print the latest value
        delay(100);  // Small delay to reduce spam in serial monitor
        startADC();  // Start next ADC conversion
    }


analogWrite(1,analogValue);
 //Serial.println(angle);
 // ServoTest.write(angle);


angle=0;
ServoTest.write(analogValue);
delay (500);
angle=45;
ServoTest.write(angle);
delay (500);
angle=90;
ServoTest.write(angle);
delay (500);
angle=135;
ServoTest.write(angle);
delay (500);
angle=180;
ServoTest.write(angle);
delay (500); 


}
// **Function to Start ADC Conversion**
void startADC() {
    ADMUX = (1 << MUX0);  // Select A1 (P2) as input channel
    ADCSRA = (1 << ADEN)  |  // Enable ADC
             (1 << ADIE)  |  // Enable ADC interrupt
             (1 << ADSC)  |  // Start conversion
             (1 << ADPS2) | (1 << ADPS1); // Set ADC clock prescaler (64 → 125kHz)
}

// **ADC Interrupt Service Routine (ISR)**
ISR(ADC_vect){
    analogValue = ADC;  // Read ADC result
    adcReady = true;  // Set flag to indicate new data is available
}

Checking that Digispark Board can drive SG90 Servo Motor at DPin-0 (PB0).
You need to install ATTinyCore as per instructions of the attached file..

1. Please, connect a SG90 type Servo Motor with DPin-0 (PB0) of Digispark ATtiny85 Board.

2. Upload the following sketck (tested).

/* Sweep
 by BARRAGAN <http://barraganstudio.com>
 This example code is in the public domain.

 modified 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Sweep

 If Servo library is installed to libraries, then that version (which doesn't support ATtiny parts)
 will be used instead of the one included with the core, which does. To get around this,
 include  Servo_ATTinyCore.h instead - this will always use the version that came with core.
*/

#include <Servo_ATTinyCore.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() 
{
  myservo.attach(0);  // attaches the servo on pin 9 to the servo object
}

void loop() 
{
  for (pos = 0; pos <= 180; pos += 1) 
  {                                   // goes from 0 degrees to 180 degrees// in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) 
  {                                   // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
}

3. Check that the Servo is turning to-and-fro.
4. Now, connect Pot at Ch-1 of ADC (PB2) to control the position of the shaft of the Servo Motor.

5. Upload the following sketch (tested).

#include <Servo_ATTinyCore.h>

Servo myservo;

void setup()
{
  myservo.attach(0);  
}

void loop()
{
  int y = analogRead(A1);
  byte position = map(y, 0, 1023, 0, 180);
  myservo.write(position);
  delay(1000);
}

6. Check that the position of the shaft changes as you rotate the Pot.
ProgrammingATtiny85 (5).pdf (172.6 KB)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.