You are here

PAS with variable assist+regen brake

1 post / 0 new
Lukas_T
Offline
Last seen: 1 day 13 hours ago
VESC Free
Joined: 2025-06-18 09:39
Posts: 1
PAS with variable assist+regen brake

Hi fellow tinkerers,

Since i struggled a bit to find answers in this forum i figured I'll upload my lisp script that i used now for 800km (16km of altitude, there are roughly 400m/20km)  while commuting. This worked for me to get variable pedal assist level with regen-braking (thumb throttle in rear brake lever). I use the grintech (9c) RH212, a flipsky 75100 pro v2, a 4 wire pas sensor and a 14s 25ah battery from cham rider. I just updated my firmware to the 6.06 version (I think) and the script works fine with it. I hope this helps someone out there, as it would have helped me ;)

 

Cheers

 

;this is a combination of the codes from blowman (vesc forum) and ebike builder (youtube). i can only partially take credit for it
;run the vesc esc in the adc app (control type 'Current No ReverseBrake ADC2'). i used a 12 pole 4 wire pas sensor that is connected to rx and tx pins of the uart connection
;the code figures out if pedaling is present and then maps the adc1 to the throttle, this gives a constant torque pas. I removed the spring from a thum throttle which i can now use to set the assistance i like (like suggested by blowman).
;i disassembled a second thumb throttle and put it into the handle of my rear brake. it is connected to adc2, so i can regen brake befor the disc brake engages. when the brake is pulled, assistance is switched off completely. there is a weird threshold of 1.38 V that works well for me. ususally my open brake is at 0.95 V. i suspect noise, or filtering interference...mybe a debounce timer or a state machine could be more elegant here.
;be aware: I really had to beef up my torque arm setup to prevent the axle from wiggling around when switching from forward to regen braking
;backpedaling something like two full rotations switches between legal speed limit and speed-mode. use this responsibly and not on public bike paths and streets opf courxe ;)
;i left some un-commented stuff there that is nice for trouble shooting

(gpio-configure 'pin-rx 'pin-mode-in-pd)
(gpio-configure 'pin-tx 'pin-mode-in-pd)
;config
(define invert 0)
(define pas-timeout-secs 0.25)
(define legal-erpm 5600) ; ca 26km/H with 26 inch tire, 26*1000/60/(0.660*pi)*26
(define speed-erpm 12000) ; 8150: ca 39km/h for speedmode; use profile to set absolute top speed
(define erpm 5600); start in legal mode


;state
(define pas-active 0)
(define brake-active 0)
(define pulses 0) ;positive when pedal forward
(define last-pulse-time (systime))
(define secs-since-pulse 0)
;(define pulses-per-sec 0)
;(define forwards 0) ;1 if pedaling forwards
;(define backwards 0) ;1 if pedaling backwards
;(define stopped 1) ;0 if pedaling forward or backwards, 1 if stopeed

(define rx 0)
(define rx-prev 0)
(define tx 0)
(define tx-prev 0)

;use this to set pas active
(defun set-pas-active (new-pas-active)
 (progn
    ; only run this if value is changing
    (if (not-eq pas-active new-pas-active)
     (progn
        (define pas-active new-pas-active)
        
        (if (eq pas-active 1)
         (print "pas active"))
        
        (if (eq pas-active 0)
         (progn
            (print "pas stop")
            (define pulses 0)
;            (define pulses-per-sec 0)
         )
        )
     )
    )
 )
)

(defun set-brake-active (new-brake-active)
 (progn
    (if (not-eq brake-active new-brake-active)
     (progn
        (define brake-active new-brake-active)
        
        (if (eq brake-active 1)
         (print "brake active"))
        
        (if (eq brake-active 0)
         (progn
            (print "brake stop")
            (define pulses 0)
;            (define pulses-per-sec 0)
         )
        )
     )
    )
 )
)     

; called when pas pulse detected
(defun pulse-detected (direction)
 (progn
    ; pas inverted check
    (if (eq invert 1)
        (if (eq direction 1)
            (define direction 0)
        )if (eq direction 0)
            (define direction 1)
    )
    
    (if (eq direction 1) ;forwards
     (progn
;        (print "pulse-detected: forwards")
        (define pulses (+ pulses 1))
        (define last-pulse-time (systime))
;        (define forwards 1)
;        (define backwards 0)
;        (define stopped 0)
        
        ; check if pas should start
        (if (and (eq pas-active 0) (>= pulses 2))
         (progn
            (set-pas-active 1)
            (set-brake-active 0)
         )
        )
     )
    );else
    (if (eq direction 0)
     (progn
;        (print "pulse-detected: backwards")
        (define pulses (- pulses 1))
        (define last-pulse-time (systime))
        (set-pas-active 0)
;        (define backwards 1)
;        (define forwards 0)
;        (define stopped 0)
        
        ; check if brake should start 
        (if (and (eq brake-active 0) (<= pulses -40))
         (progn
            (set-brake-active 1)
            (set-pas-active 0)
         )
        )
    ))
 
 )   
)    

;runs in main loop to process pas-state
(defun update-pas-state ()   
 (progn
    (define secs-since-pulse (secs-since last-pulse-time))
    
    (define rx-prev rx) ;save previous rx
    (define rx (gpio-read 'pin-rx)) ;update rx   
    
    (define tx-prev tx) ;save previous tx
    (define tx (gpio-read 'pin-tx)) ;update tx
    
    ;logic to invert direction
    (define fwd (if (eq invert 1) 1 0))
    (define back (if (eq invert 1) 0 1))
    
    ;detect rising and falling edges on rx
    (if (and (eq rx 1) (eq rx-prev 0)) ;rising edge on rx
        (if (eq tx 0)
            (pulse-detected fwd)
            ;else
            (pulse-detected back)
        )
        
        (if (and (eq rx 0) (eq rx-prev 1))
            (if (eq tx 1)
                (pulse-detected fwd)
                ;else
                (pulse-detected back)
            )
        )
    )
    
    ;pas timeout detection
    (if (and (eq pas-active 1) (> secs-since-pulse pas-timeout-secs))
     (progn
        (print "pas timeout")
        (set-pas-active 0)
     )
    )
    
    ;brake timeout detection
    (if  (and (< pulses -2) (> secs-since-pulse pas-timeout-secs))
     (progn
        ;(print "brake timeout")
        (define pulses 0)
        (set-brake-active 0)
      )
     )
 )
)

;main loop   
(loopwhile t
 (progn
    (update-pas-state)

   
    (if (and (eq pas-active 1) (<= (get-rpm) erpm) (< (get-adc 2) 1.38)) ;map adc1 to throttle when pedaling, below erpm setpoint and no pulled brake
      (app-adc-detach 1 0)
      (app-adc-detach 1 2)
      )
      
    (if (eq brake-active 1) ;on 'brake-active' switch between legal and speed mode; actual regen brake is activated by adc2
     (progn
        (if (eq erpm legal-erpm)
            (progn
                (define erpm speed-erpm)
                (print "speed-mode") 
                (set-brake-active 0)

            );else
            (progn
                (define erpm legal-erpm)
                (print "legal-mode")
                (set-brake-active 0)

            )
        )
      )
     ) 
      
     
    
    (sleep 0.005) ; run at 200Hz
 )
)