Digispark (ATtiny85) and L9110

I'm having trouble getting a motor to spin in two directions. I'm using a Digispark and an L9110 motor controlller. Power comes from 6xAAA batteries (9V) split to the motor controller and the Digispark's VIN pin.

These motor controllers only have two control pins instead of three. Setting one pin to low and the other to a PWM value of 0-255 makes the motor spin in one direction; flip the pins and the motor should spin the other way.

But I can't get the motor to spin in the alternate direction using a Digispark, even though I've tried all combinations of the ATtiny85's three PWM pins. Here's the full code:

#include <VirtualWire.h>
int A_IA = 1; //motor controller pin 1 (PWM) 
int A_IB = 4; //motor controller pin 2 (PWM)

// inputs
const int receive_pin = 2; //433mhz receiver pin

// Variables
char x;
double sensorArray[1] = {};
boolean newData = false;
int PWMvalue = 0; //PWM command sent to the motor controller
int PWMprevvalue = 0; //PWM storage for power on/off button
bool forward = true; //set Motor direction

void setup() {
   Serial.begin(9600);
  vw_set_rx_pin(receive_pin);
  vw_set_ptt_inverted(true); //VirtualWire, Initialise the IO and ISR. Required for DR3100
  vw_setup(2000); //Bits per sec
  vw_rx_start(); //Start the receiver PLL running
  pinMode(A_IA,OUTPUT);
  pinMode(A_IB,OUTPUT);
  digitalWrite(A_IA, LOW); //motor pin 1 off
  digitalWrite(A_IB, LOW); //motor pin 2 off
}

void loop() {
  recvOneChar();
  controlMotor();
}

void recvOneChar() {

  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  // Non-blocking
  if (vw_get_message(buf, &buflen))   {
    newData = true;
    memcpy(sensorArray, buf, buflen);
    x = sensorArray[0]; // == x;
  }
}

void controlMotor() {
  if (newData == true) {

    switch (x) {

      case '1': {  //Stop/Resume function
          if (PWMvalue > 0) {  //Motor is in motion
       PWMprevvalue = PWMvalue;  //save current ENA value
       PWMvalue = 0;   //set speed to zero
      }
      else                // current speed is zero
       PWMvalue = PWMprevvalue;  //restore last known speed
        }
        setMotorSpeed();
        break;

      case '2': { //change direction
         analogWrite(A_IA, 0);
          analogWrite(A_IB, 0);
          delay(500);

          if (forward == true) {
            forward = false;
          }
          else 
            forward = true;
        }
          setMotorSpeed();
        break;

      case '3': {  // decrease motor speed
          PWMvalue-=10;
         if (PWMvalue<60) {
            PWMvalue=0;     // min motor speed
      }
      
      }
          setMotorSpeed();
        
        break;

      case '4': { //increase motor speed
         PWMvalue+=10;
          if (PWMvalue<60) {
            PWMvalue=60;
          }
          if (PWMvalue>255) {  
              PWMvalue=255;   //max motor speed
          }
        
      }
          setMotorSpeed();
        break;
    }
    Serial.println(x);
    Serial.println(PWMvalue);
    newData = false;
  }
}

void setMotorSpeed()
{
  if (forward == true) {
    analogWrite(A_IA,PWMvalue);
    analogWrite(A_IB,0); //sets Motor speed forward
  }
  else {
    analogWrite(A_IA,0);
    analogWrite(A_IB,PWMvalue); //sets Motor speed reverse
  }
}

I've tried the code on a Nano (swapping pin values to appropriate ones for that board) and the code works with no problems. The issue on the digispark is that when I switch to the 'direction' case (case 2), the motor just stops. Trigger that case again and it restarts. If I use one of the non-PWM pins then the motor spins in the opposite direction but at maximum speed (so I have no PWM control).

Has anyone else got these motor controller boards working on a Digispark? Is there some limitation to these boards, that they can't run two PWM pins?

SOLUTION FOUND

Digisparks have three PWM pins: 0, 1 and 4. HOWEVER, pins 0 and 1 operate on a lower PWM frequency to 4 (504Hz vs 1007Hz). This prevents motor controllers from working properly on the lower-frequency pins.

The solution is to find the file core_build_options.h, usually located in C:/Users*(username)*\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\tiny. Open this file, and find the line:

#define FAVOR_PHASE_CORRECT_PWM 1

Change the 1 to a 0, then recompile the sketch. The frequency of Pin 1 has been raised to 1007Hz, to match Pin 4. Pin 0 is unaffected.

This got my motor driver working, so I'm leaving it here for anyone else struggling with ATTiny85 chips.

1 Like