Nissan Leaf park actuator motor

Nissan Leaf/e-NV200 drive stack topics
Post Reply
User avatar
J0hannes
Posts: 120
Joined: Sat Nov 11, 2023 10:29 am
Location: Finland
Has thanked: 16 times
Been thanked: 141 times

Nissan Leaf park actuator motor

Post by J0hannes »

In case someone wonders what this is made of, I happened to open one "accidentally"
If you remove the srcews which hold the actuator on the sheetmetal part, the motor splits.
Leaf park actuator (1).jpg
This is SO COOL!!!
There is a Cycloid gear drive in this :D
Leaf park actuator (5).jpg
Leaf park actuator (4).jpg
The motor is a switched reluctance motor
Leaf park actuator (2).jpg
Two SOT-23 hall sensors I0F scribed on packaging --> Could this be TI DRV5023?
Two SOT-223 502A 5394 82 --> Voltage regulators for hall sensors?
Leaf park actuator (3).jpg
User avatar
PaulHeystee
Posts: 124
Joined: Mon Apr 12, 2021 10:26 am
Location: Nederland
Has thanked: 2 times
Been thanked: 27 times

Re: Nissan Leaf park actuator motor

Post by PaulHeystee »

Hi, Just for your information; I have a developed a controller for these park motors, based on Adafruit CAN Feather or Rapsberry PR2040 Zero. It can be controlled by CAN (feather board only) or analogue (switch)

If anybody is interested please send me a DM
User avatar
GregFordyce
Posts: 11
Joined: Sun May 23, 2021 5:58 pm
Has thanked: 8 times
Been thanked: 5 times

Re: Nissan Leaf park actuator motor

Post by GregFordyce »

Over on this forum user dddrewski has posted his park pawl implementation using a Cloudray 3-Phase Stepper Motor Driver 3DM580S driven by an Arduino Nano. It's not complete but there's enough there to get started.
Here's the wiring diagram as built, and the arduino nano program to run the transmission park pawl motor.
The first time it runs, the park indicator light flashes. You push the park button and it will do a homing routine to move to park, and remember the position.
The arduino stays powered all the time, so it remembers to state of the park pawl after that.

I there are a couple of voltage dividers in there that I didn't write down the resistor values. I don't remember, but they're probably in the 100k ohm range. They result in the nano only seeing 5V on inputs.

I also didn't write down the resistor value on the LED output. It was a 3V LED, so I just tried a few values until it read 3V across the LED.

The only thing I may change is to put the Resolve-EV controller into Neutral when park is activated. Right now, it will go into park while the Resolve-EV is in Drive or Reverse.
Park Pawl Diagram.jpg

Code: Select all

//arduino program written for the nano
//this program is to control the park pawl motor on a nissan leaf transmission


#include <Encoder.h>

// IO 
const int encA = 2;  
const int encB = 3;
const int driveEnable = 4;
const int driveDir = 5;
const int drivePulse = 6;
const int senseIgnition = 7;
const int senseBrake = 8;
const int buttonsRND = 10;
const int buttonP = 11;
const int parkIndicator = 12;

// Other constants
const int posDrive = 0; // in encoder counts
const int posPark = -450; 

const float PulsePerCount = 2.661290323; //encoder counts divided by drive pusles
const int posError = 5;  //number of counts of the encoder that it can vary without causing an error. Also used for the power up routine to find the end of travel.
const int pulseWidth = 1; //in miliseconds for the stepper drive pulse width
const int pulsesPerErrorCheck = 10; 

const int inPark = 1;
const int inDrive = 2;
int pawlState = 0;

Encoder pawlEncoder(encA, encB);

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);

// IO Pin Assignments
pinMode(driveEnable,OUTPUT);
pinMode(driveDir,OUTPUT);
pinMode(drivePulse,OUTPUT);
pinMode(buttonsRND,INPUT_PULLUP);
pinMode(buttonP,INPUT_PULLUP);
pinMode(senseBrake,INPUT);
pinMode(senseIgnition,INPUT);
pinMode(parkIndicator,OUTPUT);


digitalWrite(driveEnable,HIGH); // disable current to the motor

// On power up, assume unknown position. Flash park button until pressed and do homing
while(!(!digitalRead(buttonP) && digitalRead(senseBrake) && digitalRead(senseIgnition))){
  digitalWrite(parkIndicator, HIGH);
  delay(200); // delay for park indicator to flash on and off showing it needs to be pressed
  digitalWrite(parkIndicator, LOW);
  delay(200);
  }

// wait for button release
while(!digitalRead(buttonP)){}

// move to park until a following error is detected (hard stop)
pawlEncoder.write(0);
movePawl(posPark);
delay(2000); // if pressed up against the hard stop, let mechanism relax before zeroing the encoder
pawlEncoder.write(posPark);
pawlState = inPark;

}

void loop() {
// put your main code here, to run repeatedly:

// check if the following is true: RND pressed, brake pressed and ignition on -> go to drive position
if(digitalRead(buttonsRND) && digitalRead(senseBrake) && digitalRead(senseIgnition) && (pawlState == inPark)){
	movePawl(posDrive);
  pawlState = inDrive;
  }   	

// check if the following is true: P pressed, brake pressed and ignition on -> go to park position
if(!digitalRead(buttonP) && digitalRead(senseBrake) && digitalRead(senseIgnition) && (pawlState == inDrive)){
 	movePawl(posPark);
	pawlState = inPark;
	}
   	
// set the state to the correct state while the ignition is on
if(digitalRead(senseIgnition) && (pawlState == inPark)){digitalWrite(parkIndicator, HIGH);}
else{digitalWrite(parkIndicator, LOW);}

}	

int indexA;
int indexB;
long startposition;
int direction;
int errorstate;

void movePawl(int targetposition){

// get the motor ready to run
digitalWrite(driveEnable,LOW);
delay(100); // wait for drive enable to take effect
startposition = pawlEncoder.read();
errorstate = LOW;

// set the motor direction
if (targetposition < startposition){
  direction = -1;
  digitalWrite(driveDir, LOW);
  delay(5); // delay per timing chart for drive on control signal changes
  }
  else {
  direction = 1;
  digitalWrite(driveDir, HIGH);
  delay(5); // delay per timing chart for drive on control signal changes
  }

// move the motor until target position is reached, or position error is detected
indexA = 0;
while (!errorstate && !checkInposition(targetposition,direction)){
  indexB = 0;
  while (indexB < pulsesPerErrorCheck){
    digitalWrite(drivePulse, HIGH);
    delay(pulseWidth);
    digitalWrite(drivePulse, LOW);
    delay(pulseWidth);
    indexB ++;  
    }
  indexA ++;

  // check the current position against the expected position
  if ( abs(startposition + direction*indexA*indexB/PulsePerCount - pawlEncoder.read()) > posError){
    errorstate = HIGH;
    }   
  }

digitalWrite(driveEnable,HIGH); // move done, disable current to motor
}

int checkInposition(int targ, int dir){
  if(dir==1){
    return(pawlEncoder.read() > targ);
    }
  else{
    return(pawlEncoder.read() < targ);
  }
}
 
Peugeot Expert LWB 2009
Zombieverter - Full 80kW Leaf stack
24kWh & 30kWh Leaf batteries in custom battery box under van
Post Reply