Controlling a central lock motor: hints on software approach needed

While being fairly new into programming I managed to work my way through most of the parts I need for my project such as PWM, OLED, temperature sensors, etc via tutorials and examples.
However, on this one I am stuck, probably because I am not taking the correct approach and/or do not understand the relevant examples. Hope you can help me out.

I want to control a central locking motor to move a valve. Mechanically it is all in place, see attached photo.
In terms of electronics I am using the Infineon TLE52062SAKSA1 motor driver chip.
My microcontroller is a Teensy 3.6.
The central locking motor has some feedback whether it is in the open or closed position. The active position is grounded and the other one then is not connected. This switches somewhere halfway.
I have implemented these as an input with a pullup.
Moving the motor back and forward using the motor driver chip works fine.
However, I am running into difficulties actually controlling it using a momentary push button.
What I am basically after is:

  • If 'button pressed' and 'open position' => close
  • If 'button pressed' and 'closed position' => open
    I've tried something with if and else statements but as a result the motor gets powered too long or too short.
    What I need is if the button is pressed (no matter how long or short) this is seen as a trigger to power the motor just long enough to get the valve to the other side. Hope you can guide me in the right direction for:
  • Interpreting the button push as a trigger/pulse
  • Finding a way to give the motor enough time to move the valve without using the delay function in the code

This is my code so far, but that is not working and still uses delays....

//Teensy 3.6_2
#define RESET_WATCHDOG 23
int motor_direction1_pin = 14; // Ampseal 35.2_35 this one H=close (motor green wire)
int motor_direction2_pin = 36; // Ampseal 35.2_34 this one H=open (motor blue wire)
int recirc_switch_pin = 7; // Pin for receiving the manual recilculation signal
int recirculate_open_pin = 19; // Positions of CV motor => low = open (pulled) | high is not open
int recirculate_closed_pin = 8; // Positions of CV motor => low = closed (pushed away) | high is not closed
int recirculate_position = 0; // Use this variable to store flap position OPEN = fresh air = 0 (LOW) and CLOSED = interior air = 1 (HIGH)
int manual_recirc_control = 0; // Variable for reading if button is pressed
int next_valve_action = 1; //Variable for storing next valve direction. Case 1 = go open and Case 0 = go close

void setup() {
  // put your setup code here, to run once:
  pinMode(recirc_switch_pin, INPUT); // 
  pinMode(motor_direction1_pin, OUTPUT); //
  pinMode(motor_direction2_pin, OUTPUT); //
  pinMode(recirculate_open_pin, INPUT); //
  pinMode(recirculate_closed_pin, INPUT); //

  Serial.begin(9600);      // turn on Serial Port

}

void loop() {
  // put your main code here, to run repeatedly:
  ResetWatchdog ();
  recirculate_position = digitalRead(recirculate_open_pin);
  manual_recirc_control = digitalRead(recirc_switch_pin);
if (recirculate_position == HIGH) {
  next_valve_action = 1;
  }
  else{
    next_valve_action = 0;
  }


//OPEN FLAP
  if (manual_recirc_control == HIGH && next_valve_action == HIGH ) { // check if the input is HIGH (button pressed) and recirc. open
    digitalWrite(motor_direction1_pin, HIGH);
    digitalWrite(motor_direction2_pin, LOW);
    delay(200);
    digitalWrite(motor_direction1_pin, LOW);
    digitalWrite(motor_direction2_pin, LOW);
    next_valve_action = LOW;
  }
  else
  { digitalWrite(motor_direction1_pin, LOW);
    digitalWrite(motor_direction2_pin, LOW);
  }
  delay(200);


//CLOSE FLAP
  if (manual_recirc_control == HIGH && next_valve_action == LOW ) { // check if the input is HIGH (button pressed) and recirc. open
    digitalWrite(motor_direction1_pin, LOW);
    digitalWrite(motor_direction2_pin, HIGH);
    delay(200);
    digitalWrite(motor_direction1_pin, LOW);
    digitalWrite(motor_direction2_pin, LOW);
   }
  else
  { digitalWrite(motor_direction1_pin, LOW);
    digitalWrite(motor_direction2_pin, LOW);
  }
  delay(200);


  //Output what is happening
  Serial.print("Recirculate position: ");
  Serial.println(recirculate_position);
  Serial.print("Recirculate switch: ");
  Serial.println(manual_recirc_control);
  delay(100);


}


void ResetWatchdog()
{
  //Serial.println("Watchdog about to Reset");
  pinMode(RESET_WATCHDOG, OUTPUT);
  delay(200);
  pinMode(RESET_WATCHDOG, INPUT);
  //Serial.println("Watchdog Reset");
}

What do you mean by "is not working"?

Do you have a simpler program that just locks (or unlocks) the motor?

How are you powering the motor? How is it all wired up?

Thanks for your reply.
Sorry, "not working" it not adding much value as a problem statement.
The motor is being powered by a H-bridge (see attached schematic).
That bridge needs IN1 and IN2.
I got it working to the point where I just use a wire to ground "recirc_switch_pin" and do it short enough the motor moves the flap. The I'd manually switch the polarity of the motor and it worked the other way.
It became a mess when I wanted to include the direction and use a real button.
Unfortunately I'v overwritten that "working" code.

Currently I am at the point that I can include the direction (with the code above), but it is kind of random due to the delays.
Plus is slams too much so I need to PWM then LOW in towards the motor driver. But them the delay is not correct anymore and it continues to pull even the motor has come to the end of it's travel.

oudevolvo:
Currently I am at the point that I can include the direction (with the code above),

Your code seems to have extraneous stuff such as watchdogs. Take everything out except the bare minimum to move the motor and detect its position.

I think the concept of a state-machine (look it up) will help with this. (State-machine is just a fancy word for a system that uses a variable to keep track of the state of the system. For your system the states might be

Open
Closing
Fastened
Unfastening

You could have a char variable (let's call it lockState) that can hold any of the letters O C F or U to signify the state

The other big attraction of this sort of system is that it separates the inputs from the outputs

The way it would work would be like this

On the input side, if the button is pressed and lockState == 'O' the state changes to 'C'

On the output (motor) side the motor code continuously monitors lockState and if it sees a 'C' it causes the motor to move to close the lock.

And on the detection side the code that checks for the position of the motor will change lockState to 'F' when it is triggered in the closed position.

If the motor side sees that lockState is not a 'C' it will stop moving the motor.

I'm assuming you can extend the idea to the opening phase.

...R

Thanks!
That sure helps. Will explore the state machine approach and try to implement it.
Using a char is a nice idea too, make it easier to understand. Now I have to check "what did low/high mean?"
Watchdog is bare minimum by the way. The Teensy is on a bigger PCB that wires the motor driver and the board also have a watchdog bolted in that I cannot easily remove.
At first I did not have the watchdog code implemented and wondered why the Teensy became unresponsive/offline after evert 10 seconds. It was the watchdog resetting it since the dog was not patted. So not I at least know that works :wink:

oudevolvo:
Using a char is a nice idea too, make it easier to understand.

If you figure out how to use ENUMs it will be even easier to understand - but perhaps one step at a time.

...R

Have done some reading on ENUMs. Though I do not yet fully understand it or have it working, I think this is the way forward for me, thanks for introducing that concept to me.

A quick recap on the above / initial challenge. The central lock motor had two position feedback wires. One grounded pushed out and one grounded pulled in. I assumed it would get grounded at the end of the travel. However, it turned out to be that one wire is not adding much value since it switches in the middle. So I'll have to work with motor enable duration to get the flap/valve to the other side. Of course possible, but difficult to get it exact.
So I have decided to try another approach: use a servo instead. I have modified the valve/flap so it moves smoothly and easily. Then I can just use a library to instruct "move to X degrees" and I'm done.

Nevertheless I will dive deeper into ENUMs since I have some LED's to switch under different circumstances.
Is my understanding of ENUMs correct that the basic idea is that:

  • You use a piece of code (often some IF statements) to tell in which state the machine is and initially there always is some kind of "ready" state defined
  • You use another piece of code (can even be a function at the bottom outside the loop) to define what needs to happen in each state?

oudevolvo:
Is my understanding of ENUMs correct that the basic idea is that:

ENUMs are just a convenient way of naming things rather than using a char variable which single letters to represent things.

Behind the scenes this code (from my link)

enum motorStateENUM {
    WAITING,
    FIRSTRUN,
    BETWEENRUNS,
    SECONDRUN,
    FINISHED,
};

just uses the value 0 everywhere it sees "WAITING" and the value 1 where it sees "FIRSTRUN" etc

But the word "WAITING" is more meaningful for the programmer than the number 0

...R

Hi,
Ops circuit;


Can you please show us a complete circuit, include the motor and the Teensy.
Just a diagram of the IC is not enough.
Please include how you have the power supply wired.

Thanks.. Tom... :slight_smile: