Attiny85 wireless motor control sketch

Hi there!
I’m building some feedback units for a game controller, and I have them working with cables but I really want them wireless.

I have a Nano with a 433MHz transmitter and two Attiny85 with receivers and 3xAA battery packs. The idea is to put a transistor on the 'tinys output to the motor.

I got it “working” with just LEDs instead of motors, but it seems like I missed something when it comes to serial communication. I want a steady output signal, but it seems like I get some characters “in between” so the LEDs flicker. Could anybody point me in the right direction?

This is the code I have in the transmitter. It sends “0” when nothing is pressed, “1” when button 1 is pressed and “2” when button 2 is pressed:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(11, 10); // RX, TX

const int trigger1 = 3;    // button1 pin
const int trigger2 = 4;    // button2 pin
const int on1 = 1;          // value1 on
const int on2 = 2;          // value2 on
const int off = 0;          // Off, well off..
int triggerstate1 = 0;     // button1 status variable
int triggerstate2 = 0;     // button2 status variable

void setup() {
  // open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // set data rate for softserial
  mySerial.begin(2400);

  // set pin settings
  pinMode(trigger1, INPUT_PULLUP);
  pinMode(trigger2, INPUT_PULLUP);
}

void loop() { 
  // read trigger value
    triggerstate1 = digitalRead(trigger1);
    triggerstate2 = digitalRead(trigger2);
  
  // check if trigger is pressed
  if (triggerstate1 == LOW)   {
    // send serial data "1" 
    mySerial.write(on1);
    Serial.print("T1:");
    Serial.println(triggerstate1);
    
  } else if (triggerstate2 == LOW){
    // send serial data "2" 
    mySerial.write(on2);
    Serial.print("T2:");
    Serial.println(triggerstate2);
  } else {
    // send serial data "0"
    mySerial.write(off);
  }

//delay(1);
}

The receiver code is quite simple, but I guess here is where I have my problem. I’m guessing there is some serial command that makes sure I just listen to the actual “1” or “0” characters. Now it seems I get stuff in between.

#include <SoftwareSerial.h>
  // define serial pins
SoftwareSerial mySerial(1,2);   //(RX,TX)
const int pin0 = 0;

void setup()
{
  //define motor pin as output
  pinMode(pin0, OUTPUT);
  //initiate softserial
  mySerial.begin(2400);
}

void loop()
{ if(mySerial.available() > 0)
{
if (mySerial.read() == 1) {
  // turn motor on
  digitalWrite(pin0,HIGH);
    } else {
  //turn motor off
  digitalWrite(pin0,LOW);
    }
  }
delay(1);
}

If someone could point me in the right direction, I’d be very grateful! :smiley:

//Chris

These lines

const int on1 = 1;          // value1 on
const int on2 = 2;          // value2 on
const int off = 0;          // Off, well off..

create constants that are 16 bits, so when you do a write(), you are sending 2 bytes, one of which is a 0. Change them to

const byte on1 = 1;          // value1 on
const byte on2 = 2;          // value2 on
const byte off = 0;          // Off, well off..

Good point! :smiley:
That would probably make every other byte a zero on the receiving side then?

I’ll try it out tomorrow, thanks!

It doesn’t seem to make any difference unfortunately. The test LED is still flickering.

I tried to make an “delay off” function, but it doesn’t seem to work either.

Any ideas?

Receiver code:

#include <SoftwareSerial.h>
  // define serial pins
SoftwareSerial mySerial(1,2);                             //(RX,TX)
  // define output pin
const int motorPin = 0;
  // stuff for delay
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long holdtime = 10;                        //time held before turning off

void setup()
{
  //define motor pin as output
  pinMode(motorPin, OUTPUT);
  //initiate softserial
  mySerial.begin(2400);
  //some more delay stuff
  startMillis = millis();                                 //initial start time
}

void loop(){ 
  if(mySerial.available() > 0){
      if (mySerial.read() == 1) {
      // turn motor on
      digitalWrite(motorPin,HIGH);
    } else {
      //turn motor off after 'holdtime'
      currentMillis = millis();                           //the time right now
      if (currentMillis - startMillis >= holdtime) {      //test whether the holdtime has elapsed
      digitalWrite(motorPin,LOW);
      }
   }
delay(1);
  }
}

close. You need to set your startMillis variable when you set the LED HIGH

#include <SoftwareSerial.h>
// define serial pins
SoftwareSerial mySerial(1, 2);                            //(RX,TX)
// define output pin
const int motorPin = 0;
// stuff for delay
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long holdtime = 10;                        //time held before turning off

void setup()
{
  //define motor pin as output
  pinMode(motorPin, OUTPUT);
  //initiate softserial
  mySerial.begin(2400);
  //some more delay stuff
  startMillis = millis();                                 //initial start time
}

void loop() {
  currentMillis = millis();                           //the time right now
  if (mySerial.available() > 0) {
    if (mySerial.read() == 1) {
      // turn motor on
      digitalWrite(motorPin, HIGH);
      startMillis = currentMillis;
    } else {
      //turn motor off after 'holdtime'
      if (currentMillis - startMillis >= holdtime) {      //test whether the holdtime has elapsed
        digitalWrite(motorPin, LOW);
      }
    }
    delay(1);
  }
}

Yeah, thanks, I actually found that too!

However, even if I got this working it seems like I get too much noise on the RX.
Googled a bit and landed on the RadioHead library.
Makes no sense to me yet, but it seems to support what I want to do, but with checksums and all that fancy wireless things that I’m starting to get the point of…

I’m trying to wrap my head around it, and I’ll get back to you guys for support when I have some semi working code!

Unfortunately I couldn’t cramp the RadioHead in to the Tiny…

Went another path, and now I’m transmitting square waves of different frequencies depending on what button is pressed.
Works great, but I’m having trouble when I connect the motors (as suspected). If I just drive small motors or leds it works just fine.
Probably it has something to do with ripple currents from the motor or just the voltage dip at the start.
Could also be the motor disturbing the 433MHz signal.

Anyhow, the “working” code for anyone interested:

Transmitter:

int TX = 10;
int one = 3;
int two = 4;

void setup() {
pinMode(TX,OUTPUT); 
pinMode(one,INPUT_PULLUP); 
pinMode(two,INPUT_PULLUP); 

}

void loop() {

  if(!digitalRead(one))
  {
    write_freq(1300);
    } else if (!digitalRead(two)){
      
    write_freq(2500);
  } else {
    write_freq(4000);
  }


}


void write_freq(int DELAY)
{
  digitalWrite(TX,LOW);
  delayMicroseconds(DELAY);
  digitalWrite(TX,HIGH);
  delayMicroseconds(DELAY);
}

Receiver 1:

int RX = 3;
int motorPin = 0;
int pin_state= 0;
unsigned long counter = 0;
unsigned long prev_counter = 0;
long DELAY = 0;
float freq = 0;


unsigned long previousMillis = 0; 

void setup() {
  pinMode(RX,INPUT);
  pinMode(motorPin,OUTPUT);
}

void loop() {

  unsigned long currentMillis = millis();  
  if(currentMillis - previousMillis >= 100){
  
      previousMillis += 100;
      if(DELAY > 800 && DELAY <1800)
      {
      digitalWrite(motorPin,HIGH);
      } else {
      digitalWrite(motorPin,LOW);
      }
   
  }

  
 if(digitalRead(RX) && pin_state== 0)
 {
  pin_state=1;
  prev_counter = micros();
 }

 if(!digitalRead(RX) && pin_state== 1)
 {
  pin_state=0;
  counter = micros();
  DELAY = counter - prev_counter;   
 }
 
}

Receiver 2

int RX = 3;
int motorPin = 0;
int pin_state= 0;
unsigned long counter = 0;
unsigned long prev_counter = 0;
long DELAY = 0;
float freq = 0;


unsigned long previousMillis = 0; 

void setup() {
  pinMode(RX,INPUT);
  pinMode(motorPin,OUTPUT);
}

void loop() {

  unsigned long currentMillis = millis();  
  if(currentMillis - previousMillis >= 100){
  
      previousMillis += 100;
      if(DELAY > 2000 && DELAY < 3000)
      {
      digitalWrite(motorPin,HIGH);
      } else {
      digitalWrite(motorPin,LOW);
      }
   
  }

  
 if(digitalRead(RX) && pin_state== 0)
 {
  pin_state=1;
  prev_counter = micros();
 }

 if(!digitalRead(RX) && pin_state== 1)
 {
  pin_state=0;
  counter = micros();
  DELAY = counter - prev_counter;   
 }
  
 
}

Thanks to the people behind the original code: ElectroNoobs

How do you have the motors wired up? The arduino boards can not run the motors directly. You need some sort of motor driver shield/circuit and external power supply to supply enough current to drive anything meaningful. If you can drive LEDs ans small motors, I'm guessing you are trying to drive too much directly.

I have a Nano with a 433MHz transmitter and two Attiny85 with receivers and 3xAA battery packs. The idea is to put a transistor on the 'tinys output to the motor.

From the very first post.

Do you have a flyback diode across your transistor? How about a circuit diagram, even a hand-drawn one?

blh64:
Do you have a flyback diode across your transistor? How about a circuit diagram, even a hand-drawn one?

Yes I do.

Changing the circuit now to adapt it to the Esp8266 units, I’ll draw up a circuit diagram after the first working prototype is running. It will probably look something like this for the motor part of the circuit:

circuit.png