papous
Posts: 72
Joined: Fri Jan 05, 2018 5:50 am

Odd Camjam engine behaviour

Tue Mar 06, 2018 12:00 pm

I return to my previous post viewtopic.php?f=37&t=201657&p=1255442#p1254804
The problem of the engines running erratically persists and I never did get a proper answer.
My questions today are:
1.Could it be due to poor voltage(I am using the 4 battery box with rechargeable batteries)? If so, can I use a 6 pack battery box (7.2 volt) or this will destroy the engines?
2.Could it be due to a faulty controller?
3.Is it poor processing of my control module (code below) which appears to be functioning well or the threading process?
Any help/ideas would be gratefully appreciated

Code: Select all

import sqlite3
from flask import Flask,render_template, url_for, request, redirect, session
import os.path
from time import sleep
import motor
import threading
from my_functions import blink, distance_detected

tdist=[]
app=Flask(__name__)
conn = sqlite3.connect(':memory:', check_same_thread=False)
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS ways (oldway text, newway text, drive_mode text, dc int)''')
c.execute("INSERT INTO ways VALUES ('S','S','AUTO',0)")
conn.commit()

@app.route('/')
def index():
    return render_template('index.html', drive_mode='start')

@app.route('/start', methods=['POST'])
def man_auto():
    drive_mode=request.form.get('drive_mode')
    print(drive_mode)
    c.execute('SELECT drive_mode FROM ways')
    c.execute('''UPDATE ways SET drive_mode=?''',(drive_mode,))
    return render_template('index.html', drive_mode=drive_mode)

@app.route('/drive_manual', methods=['POST'])
def drive():
    c.execute('SELECT * FROM ways')
    (oldway, newway, drive_mode, dc) = c.fetchone()
    oldway=newway
    newway=request.form.get('newway')
    dist2obj = distance_detected(tdist=[])
    
    if newway=='brake':
        dc=dc-10
        if dc<0:
            dc=0
        newway = oldway
        
    if newway=='accel':
        dc=dc+10
        if dc>100:
            dc=100
        newway=oldway
    
    if newway=='S':
        dc=0

    if newway=='F' or newway=='B' or newway=='L' or newway=='R':
        pass

    if newway=='AUTO':
        newway='S'
        dc=0
        drive_mode="AUTO"

    c.execute('''UPDATE ways SET oldway=?, newway=?, drive_mode=?, dc=? ''', (oldway,newway,drive_mode,dc))
    conn.commit()
    c.execute('SELECT drive_mode FROM ways')
    all_one = c.fetchone()
    print('<-->', all_one)
    return render_template('index.html', speed=dc, drive_mode=drive_mode)


@app.route('/drive_auto', methods=['POST'])
def auto():
    stop_go=request.form.get('stop_go')
    print(stop_go)
    c.execute('SELECT * FROM ways')
    (oldway, newway, drive_mode, dc) = c.fetchone()
    print('>', oldway, newway, drive_mode, dc)
    if stop_go=='F':
        dc=30
        newway='F'
        oldway='F'
    if stop_go=='S':
        dc=0
        newway='S'
        oldway='S'   
    if stop_go=='MANUAL':
        dc=0
        drive_mode="MANUAL"
    print('->', oldway, newway, drive_mode, dc)
    c.execute('''UPDATE ways SET oldway=?, newway=?, drive_mode=?, dc=? ''', (oldway,newway,drive_mode,dc))
    conn.commit()
    c.execute('SELECT * FROM ways')
    all_one = c.fetchone()
    print('-->', all_one)
    return render_template('index.html', speed=dc, drive_mode=drive_mode)    

def loop_func():
    while True:
        c.execute('SELECT * FROM ways')
        (oldway, newway, drive_mode, dc) = c.fetchone()
        dist2obj = distance_detected(tdist=[])
        
        driveit(oldway, newway, drive_mode, dc, dist2obj)


#### START THREADS
try:
    t = threading.Thread(target=loop_func)
    t.daemon = True
    t.start()
except KeyboardInterrupt:
    GPIO.cleanup()
    
    

if __name__ == '__main__':
    app.debug = True
    app.run(host = '0.0.0.0',port=5000)
  
#############################
# proccess drive response from html
# and convert to engine commands
    
def driveit(oldway, newway, drive_mode, dc, dist2obj):
    print('--->>>', newway, dc, dist2obj)
    
    if drive_mode=='MANUAL':
        if dist2obj < 25 and newway=='F':
            newway = 'S'
        if newway == 'F':
           motor.Motor_dc(dc,dc,0,0)    
        if newway ==  'B':
            motor.Motor_dc(0,0,dc,dc)
        if newway == 'S':
            dc=0
            motor.Motor_dc(0,0,0,0)
        if newway == 'L':
            motor.Motor_dc(0,dc,dc,0)
            sleep(3)
            if oldway=='F':
                motor.Motor_dc(dc,dc,0,0)
            if oldway=='B':
                motor.Motor_dc(0,0,dc,dc)
            oldway=newway          
        if newway == 'R':
            motor.Motor_dc(dc,0,0,dc)
            sleep(3)
            if oldway=='F':
                motor.Motor_dc(dc,dc,0,0)
            if oldway=='B':
                motor.Motor_dc(0,0,dc,dc)
            oldway=newway
        if dc==0:
            blink('off')
        else:
            blink('on')            
        sleep(0.1)

    if drive_mode=='AUTO':
        if dist2obj<25:
            print(dist2obj)
            motor.Motor_dc(0,0,dc,dc)
            print('going back')
            sleep(5)
            motor.Motor_dc(0,dc,dc,0)
            sleep(4)
            print('turning')
        if newway=='S':
            dc=0
        #if newway=='F':
            #dc=dc
        motor.Motor_dc(dc,dc,0,0)
        blink('on')            

User avatar
recantha2
Posts: 287
Joined: Wed Nov 14, 2012 9:34 am
Location: Potton, Bedfordshire
Contact: Website Facebook Twitter

Re: Odd Camjam engine behaviour

Tue Mar 06, 2018 2:25 pm

Hi.
Mike here from CamJam.
If the script from the worksheets works correctly then there's nothing wrong with the hardware.
There must be, therefore, something at issue with your software. Taking a look at the software below, a few things come to mind:
First of all, I have no idea what this 'motor' library is. It's not something the CamJam worksheets provides, so maybe it's mis-use of a different library, or maybe it's one you've written yourself and it's not quite right.
Secondly, you're attempting to control the motors through a web interface. This is okay in principle but will introduce delays when you click on a control and it translates that into movement.
Thirdly, you appear to be piping the movement commands through a database and then out again. This will also introduce delay and, possibly, incorrect instructions to the motors because of it.

In summary, it's very difficult to diagnose something when you don't have all the pieces to the puzzle.
I suggest that you go back to basics, try a bit at a time and find out when the problem first rears it's head. Debugging is all about breaking something down into it's constituent parts, testing each part and working out where it's letting you down.
--
Michael Horne - @recantha
Raspberry Pi blog - http://www.recantha.co.uk/blog

Cambridge Raspberry Jam
Website: http://camjam.me
Facebook: https://www.facebook.com/cambridgeraspberryjam
Follow the Cambridge Raspberry Jam on Twitter - @cambridgejam

papous
Posts: 72
Joined: Fri Jan 05, 2018 5:50 am

Re: Odd Camjam engine behaviour

Tue Mar 06, 2018 9:05 pm

Dear Mike,
Thank you for this very quick reply.
The 'motor' library (code below) is basically a function to move the motors according to the duty cycle.
Using sqlite3 was the only way to get the response returned from the Flask to other program sections. This was suggested to me in this post: viewtopic.php?f=32&t=203258&p=1272204#p1262528. The db is in memory so I don't expect delays or data corruption from one function to another.
Sure, there is delay getting the response from the HTML front end but once the command has reached the engines I would expect them to run without the 'hiccups' i.e. stopping and restarting on their own
If you read my previous post ( viewtopic.php?f=37&t=201657&p=1255442#p1254804 ) you would see that at that time there was no HTML front, sqlite3 or threading.
If you run my code you will see that there are 'debug' info in it, so I know that the commands reach the engines correctly.
So, are four rechargeable batteries (4.8v) enough to power the engines?
If yes what else could it be? Could you run the code in your camjam setup? I will provide the full code if you need it
Many thanks again for taking the time to help

Code: Select all

#######
#motor.py
# Orig Author: James Poole
# Date: 23 April 2016
# modified for CamJam EduKit 3 Worksheet 4

#######

try:
    import RPi.GPIO as GPIO
except RuntimeError:
    print("Error importing RPi.GPIO!  This is probably because you need superuser privileges.  ")

#import RPi.GPIO as GPIO # Import the GPIO Library
from time import sleep # Import the Time library

#print('Set the GPIO modes')
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#sleep(2)

#print(' Set variables for the GPIO motor pins')
pinMotorAForwards = 10
pinMotorABackwards = 9
pinMotorBForwards = 8
pinMotorBBackwards = 7
#sleep(2)

#print(' Set the GPIO Pin mode')
GPIO.setup(pinMotorAForwards, GPIO.OUT)
GPIO.setup(pinMotorABackwards, GPIO.OUT)
GPIO.setup(pinMotorBForwards, GPIO.OUT)
GPIO.setup(pinMotorBBackwards, GPIO.OUT)
sleep(1)

# How many times to turn the pin on and off each second
Frequency = 20
# How long the pin stays on each cycle, as a percent (here, it's 30%)
# Setting the duty cycle to 0 means the motors will not turn
DutyCycleA = 0
DutyCycleB = 0

#print('Set the GPIO to software PWM at ' ,Frequency, ' Hertz')
pwmMotorAForwards = GPIO.PWM(pinMotorAForwards, Frequency)
pwmMotorABackwards = GPIO.PWM(pinMotorABackwards, Frequency)
pwmMotorBForwards = GPIO.PWM(pinMotorBForwards, Frequency)
pwmMotorBBackwards = GPIO.PWM(pinMotorBBackwards, Frequency)
#sleep(1)

#print('start with motors stopped')
pwmMotorAForwards.start(0)
pwmMotorABackwards.start(0)
pwmMotorBForwards.start(0)
pwmMotorBBackwards.start(0)
#sleep(2)


def Motor_dc(lf,rf,lb,rb):
    pwmMotorAForwards.ChangeDutyCycle(lf)
    pwmMotorBForwards.ChangeDutyCycle(rf)
    pwmMotorABackwards.ChangeDutyCycle(lb)
    pwmMotorBBackwards.ChangeDutyCycle(rb)
          

'''
Motor_dc(70,70,0,0)
sleep (5)

GPIO.cleanup()
'''

User avatar
recantha2
Posts: 287
Joined: Wed Nov 14, 2012 9:34 am
Location: Potton, Bedfordshire
Contact: Website Facebook Twitter

Re: Odd Camjam engine behaviour

Wed Mar 07, 2018 9:18 am

Hi again.
So, two things to do:
1. Try it with 4 x 1.5V AA batteries rather than the rechargeables, just in case it _is_ that, but I doubt it because we know that others have used rechargeables without a problem.
2. Can you take all your code and upload it to Github so I can see it completely and clone it and work on it? Some instructions in the Readme.md to get sqlite running would also help - basically, I need to replicate your environment from a base Raspbian.
3. If you can, shoot a video of you using it and the strange behaviour and upload to Youtube so I can see exactly what's occurring.

My feeling is it's something very simple going wrong, but without delving more deeply into it, it's going to be an uphill struggle to do it in bits and pieces :-)
--
Michael Horne - @recantha
Raspberry Pi blog - http://www.recantha.co.uk/blog

Cambridge Raspberry Jam
Website: http://camjam.me
Facebook: https://www.facebook.com/cambridgeraspberryjam
Follow the Cambridge Raspberry Jam on Twitter - @cambridgejam

papous
Posts: 72
Joined: Fri Jan 05, 2018 5:50 am

Re: Odd Camjam engine behaviour

Wed Mar 07, 2018 12:37 pm

Thank you again for the speedy reply.
I managed to create a github account (https://github.com/fsofras) and upload everything there including a readme fle with some help.
For a video, it will take a couple of days.
If I can do something else please ask.
All the best
Frank


User avatar
recantha2
Posts: 287
Joined: Wed Nov 14, 2012 9:34 am
Location: Potton, Bedfordshire
Contact: Website Facebook Twitter

Re: Odd Camjam engine behaviour

Wed Mar 07, 2018 12:47 pm

Great. Thank you. I'll _try_ and look tonight.
--
Michael Horne - @recantha
Raspberry Pi blog - http://www.recantha.co.uk/blog

Cambridge Raspberry Jam
Website: http://camjam.me
Facebook: https://www.facebook.com/cambridgeraspberryjam
Follow the Cambridge Raspberry Jam on Twitter - @cambridgejam

papous
Posts: 72
Joined: Fri Jan 05, 2018 5:50 am

Re: Odd Camjam engine behaviour

Wed Mar 07, 2018 12:52 pm

One more thing that I feel it is important: There is a serious voltage drop on the engine terminals when the engines behave erratically. Maybe this is a clue
Frank

User avatar
recantha2
Posts: 287
Joined: Wed Nov 14, 2012 9:34 am
Location: Potton, Bedfordshire
Contact: Website Facebook Twitter

Re: Odd Camjam engine behaviour

Wed Mar 07, 2018 8:19 pm

Hi
So... I've had a go, but I get no response when clicking on the UI buttons. Flask on the command line doesn't report any pages being hit, so I guess that's a no-go, really.
Some things I recommend: At the moment, you are reloading the whole page when you click on the controls. This is overkill - you should instead take a look at Javascript Ajax so that when you click a button, it either sends a small message to the Flash app or it just hits a page in the background. You wouldn't see the output from these "page hits" because the Ajax can just send the command and 'forget' as it were.
Does that make sense?
If you take a look at JQuery, for instance, it's very easy to attach a 'click event' to the controls and send a micro Ajax request.

The scripts are very complicated, and I feel I would have to take it apart and re-construct it to do any good. That's what I suggest _you_ do: First of all, go back to basics and use just the scripts that came with the EduKit 3 worksheets. This will confirm or deny that the hardware is working correctly. Because if the hardware works, it must be your software that is the problem.
After that, do a small Flask app that *just* moves the motors forward for 5 seconds and then stops. Forget about all the PWM stuff - just concentrate on getting Flask hits to tell your motors to move. Once you've confirmed that this method *can* work, you can then start to make it more complicated.

That's what I'd do anyway. That's the way I work during my day job - pick it apart, start small and build up.
--
Michael Horne - @recantha
Raspberry Pi blog - http://www.recantha.co.uk/blog

Cambridge Raspberry Jam
Website: http://camjam.me
Facebook: https://www.facebook.com/cambridgeraspberryjam
Follow the Cambridge Raspberry Jam on Twitter - @cambridgejam

papous
Posts: 72
Joined: Fri Jan 05, 2018 5:50 am

Re: Odd Camjam engine behaviour

Thu Mar 08, 2018 6:12 am

Thanks again for taking the time to look at the project
I will take your advice and look at the code again. I did notice that running just the 'motor' module the engines work fine. So it must be software. I also found this about the RPi.GPIO module:
Note that this module is unsuitable for real-time or timing critical applications. This is because you can not predict when Python will be busy garbage collecting. It also runs under the Linux kernel which is not suitable for real time applications - it is multitasking O/S and another process may be given priority over the CPU, causing jitter in your program. If you are after true real-time performance and predictability, buy yourself an Arduino http://www.arduino.cc !
(!!)
So maybe I should change to an Arduino and learn C rather than start learning Java, JQuiry and Ajax!

User avatar
recantha2
Posts: 287
Joined: Wed Nov 14, 2012 9:34 am
Location: Potton, Bedfordshire
Contact: Website Facebook Twitter

Re: Odd Camjam engine behaviour

Thu Mar 08, 2018 7:47 am

That's all true. However, most people find the Pi's performance to be good enough in that respect. I was suggesting improvements to your approach rather than a wholesale change.
--
Michael Horne - @recantha
Raspberry Pi blog - http://www.recantha.co.uk/blog

Cambridge Raspberry Jam
Website: http://camjam.me
Facebook: https://www.facebook.com/cambridgeraspberryjam
Follow the Cambridge Raspberry Jam on Twitter - @cambridgejam

papous
Posts: 72
Joined: Fri Jan 05, 2018 5:50 am

Re: Odd Camjam engine behaviour

Thu Mar 15, 2018 3:46 pm

OK, I solved it.
This is for anyone that may have similar issues.
It is not the hardware. It is the software and specifically the combination of Flask (its debugger) and threading.
If you run the debugger (export FLASK_DEBUG=1) it spawns it own thread. This - at least in my code- interrupts the main thread and the engines loose power. Removing the debugger makes everything run smoothly.
By the way, the pigpio lib seems to work better than RPi.GPIO for motor control
All the best

Return to “Automation, sensing and robotics”