0

Using BBB without keyboard, screen, other computer
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Using BBB without keyboard, screen, other computer

by williamm8 on Tue May 02, 2017 9:36 am

I have a BBB project for a model airplane that records data such as servo position, altitude, GPS position, orientation, etc. using an auxiliary computer to start it up is very impractical at a sunlight flying field, not to mention the size and difficulty of connecting and disconnecting cables to some other device (although I did rig up an Arduino based data terminal for calibrating the BNO055 sensor.)

What I want is for the BBB to start my autopilot.py program when power is applied to the BBB. My user input for the system is the R/C transmitter, output is the system servos. I used the template in your tutorial "Running Programs Automatically on your tiny computer" from the BBB chapter.To make this work, I have to ssh into the BBB, just what I don't want to do, and run the line 'sudo systemctl start autopilot.service'. That makes everything work; my python program on the BBB is obviously running.

When I just power up the BBB from a 5V. 2A source, the BBB's python program (there's only one) clearly doesn't start. That's my problem.

Can you help me figure out what I am missing? Can my hoped-for run a program when power is applied behavior be done at all?
My BBB is running BeagleBone Debian Image 2014-04-23.

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Re: Using BBB without keyboard, screen, other computer

by pdh on Tue May 02, 2017 10:45 am

You should be able to use this command (mentioned in the systemd section of the tutorial) to automatically start the service:

sudo systemctl enable autopilot.service

The difference between "start" and "enable" is that "start" means "start it now" and "enable" means "start it whenever the system boots."
pdh
 
Posts: 169
Joined: Wed Dec 25, 2013 12:59 pm
Location: Northwest Pennsylvania

Re: Using BBB without keyboard, screen, other computer

by williamm8 on Tue May 02, 2017 1:50 pm

IMG_1325.JPG
IMG_1325.JPG (152.36 KiB) Viewed 1177 times
Thanks very much for the help. It didn't work, the system behavior is the same with "enable" as it is with "start".

I think I will try reducing the system to the point that the instructions do work, and build up from there. This may be very difficult in this case because there is a lot of hard-wired equipment plugged into the BBB. Wish me luck!

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Re: Using BBB without keyboard, screen, other computer

by drewfustini on Tue May 02, 2017 4:27 pm

Please paste the contents of autopilot.service.

It should contain a line such as this in the [Unit]:
After=generic-board-startup.service

This ensures that service will run at the correct time during bootup.

drewfustini
 
Posts: 944
Joined: Sat Dec 26, 2015 1:19 pm

Re: Using BBB without keyboard, screen, other computer

by williamm8 on Tue May 02, 2017 6:31 pm

Here is my autopilot.service:

[Unit]
Description=autopilot

[Service]
ExecStart=/root/autopilot.py
StandardOutput=null

[Install]
WantedBy=multi-user.target
Alias=autopilot.service

I would appreciate your fixing it with your suggestion, and anything else you see wrong with it.

Thanks for all the help.

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Re: Using BBB without keyboard, screen, other computer

by drewfustini on Tue May 02, 2017 11:50 pm

Please paste the output of:
systemctl status autopilot

I'd like to make sure your Python file is executable. Please paste the output of:
ls -la /root/autopilot.py

Also please attach autopilot.py or paste the contents in a reply.

drewfustini
 
Posts: 944
Joined: Sat Dec 26, 2015 1:19 pm

Re: Using BBB without keyboard, screen, other computer

by drewfustini on Tue May 02, 2017 11:57 pm

I created this test Python program:
/root/autopilot.py
#!/usr/bin/python

print("test service")

And ran:
chmod 755 /root/autopilot.py

I created this unit file:
/lib/systemd/system/autopilot.service
[Unit]
Description=autopilot
After=generic-board-startup.service

[Service]
ExecStart=/root/autopilot.py
StandardOutput=null

[Install]
WantedBy=multi-user.target
Alias=autopilot.service

Note the After= line.

And I enabled with the service with:
systemctl enable autopilot

The output was:
Created symlink from /etc/systemd/system/autopilot.service to /lib/systemd/system/autopilot.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/autopilot.service to /lib/systemd/system/autopilot.service.

drewfustini
 
Posts: 944
Joined: Sat Dec 26, 2015 1:19 pm

Re: Using BBB without keyboard, screen, other computer

by williamm8 on Wed May 03, 2017 7:50 am

I'll send the listings you requested in another reply soon. What I would have liked to see you say in this post is:
"After I type the 'enable' line, I disconnected the BBB entirely from the computer. no Ethernet cable, no USB cable or devices, just a naked BBB that could be put back in the box. Then, apply power to the BBB via the 5V. jack, and watch the test program run. "

(You'd have to add just a little to the test program to light a light or set a pin and watch it with a 'scope, since there's no screen to print test messages. In my case, I know autopilot.py is running by moving the transmitter sticks and watching the servos move)

I had better say just a little about the whole system architecture so there are no large scale misconceptions. One way to say it is that it's an aircraft R/C system with the autopilot connected between the receiver's servo outputs and the actual servos. It is intended to fly with an airplane for very short periods of time, maybe 15-30 seconds. My goal is not to make a practical autopilot product, instead it is a lab exercise for my learning about flight dynamics.

My part of the system has an Arduino listening to the receiver's servo output and measuring the pulse width. These pulse width times are sent to the BBB via i2c. They are then used to make servo pulses with the BBB's pulse generation mechanism. There are also some sensors, including GPS and your BNO055 orientation sensor, on the BBB. I did have to build an un-pluggable test display with an Arduino outside of the airplane so I can tell when I have rotated the airplane enough to calibrate the BNO055.

All of this works, including plugging and unplugging the test display, but this is with the BBB connected to my Apple with the little USB plug. No other connections other than what I have described.

I will send the listings in an hour or two - my migraine requires some rest periods.

Thanks for your dedicated, professional help.

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Re: Using BBB without keyboard, screen, other computer

by williamm8 on Wed May 03, 2017 7:55 am

I forgot to say, changing the autopilot.service file as you suggested did not change the system behavior.

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Re: Using BBB without keyboard, screen, other computer

by williamm8 on Wed May 03, 2017 9:11 am

I did a slightly interesting experiment. I plugged the BBB into it's 5V. source via the jack on the BBB's end, then plugged in the mini-USB cable that I use co connect to the Apple. I ssh'ed into the BBB, and ran autopilot.py as usual, and got the usual good result with the servos responding to transmitter stick movement. Then I unplugged the USB cable from the BBB, and the system continued to work normally with servo response from the transmitter. This last with the 5V. power the only external cable into the system.

Here are the listings you requested:

root@beaglebone:~# systemctl status autopilot
Failed to issue method call: Unit name autopilot is not valid.
----------------------------------------------------------------------------

root@beaglebone:~# ls -la /root/autopilot.py
-rwxr-xr-x 1 root root 10227 Apr 23 2014 /root/autopilot.py
--------------------------------------------------------------------------------


#!/usr/bin/python
#4-18-2017

import math
from time import sleep
import serial
import smbus
import Adafruit_BBIO.UART as UART
import Adafruit_BBIO.PWM as PWM
import Adafruit_BBIO.GPIO as GPIO
import Adafruit_BMP.BMP085 as BMP085
from Adafruit_BNO055 import BNO055
from Adafruit_I2C import Adafruit_I2C

#----------------------------------------------------------------
def readReceiverChannelsFromArduino():
global throttleTime, rudderTime, aileronTime, elevatorTime

throttleTime = 0
i2cValue = int(i2cBusForArduinoToBBB.read_byte(smbusAddress))
throttleTime = i2cValue<<8
i2cValue = int(i2cBusForArduinoToBBB.read_byte(smbusAddress))
throttleTime += i2cValue

i2cValue = int(i2cBusForArduinoToBBB.read_byte(smbusAddress))
rudderTime = 0
rudderTime = i2cValue<<8
i2cValue = int(i2cBusForArduinoToBBB.read_byte(smbusAddress))
rudderTime += i2cValue

i2cValue = int(i2cBusForArduinoToBBB.read_byte(smbusAddress))
aileronTime = 0
aileronTime = i2cValue<<8
i2cValue = int(i2cBusForArduinoToBBB.read_byte(smbusAddress))
aileronTime += i2cValue

i2cValue = int(i2cBusForArduinoToBBB.read_byte(smbusAddress))
elevatorTime = 0
elevatorTime = i2cValue<<8
i2cValue = int(i2cBusForArduinoToBBB.read_byte(smbusAddress))
elevatorTime += i2cValue

#----------------------------------------------------------------
def setServos():

aileronServoTimeF = float(aileronTime)
aileronDutyCycle = aileronServoTimeF/166.66
PWM.set_duty_cycle(aileronServoPin, aileronDutyCycle)

elevatorServoTimeF = float(elevatorTime)
elevatorDutyCycle = elevatorServoTimeF/166.66
PWM.set_duty_cycle(elevatorServoPin, elevatorDutyCycle)

rudderServoTimeF = float(rudderTime)
rudderDutyCycle = rudderServoTimeF/166.66
PWM.set_duty_cycle(rudderServoPin, rudderDutyCycle)

throttleServoTimeF = float(throttleTime)
throttleDutyCycle = throttleServoTimeF/166.66
PWM.set_duty_cycle(throttleServoPin, throttleDutyCycle)

#----------------------------------------------------------------
class gps:
def __init__(self):
update200msec = '$PMTK220,200*2C\r\n'
measure200msec = '$PMTK300,200,0,0,0,0*2F\r\n'
baud57600 = '$PMTK251,57600*2C\r\n'

GPRMConly = '$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n'
GPRMCandGPGGA = '$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n'

gpsPort.write(baud57600)
sleep(0.25)
gpsPort.baudrate=57600

gpsPort.write(update200msec)
gpsPort.write(measure200msec)
gpsPort.write(GPRMCandGPGGA)

def readGPS(self):
self.haveGPGGA = False
self.haveGPRMC = False
self.fix = '0'

if gpsPort.inWaiting()==0:
return
self.sentence1 = gpsPort.readline()

if gpsPort.inWaiting()==0:
return
self.sentence2 = gpsPort.readline()

# self.sentence1 = '$GPRMC,125646.400,A,3513.2272,N,08241.9348,W,0.37,248.14,120417,,,A*7C'
# self.sentence2 = '$GPGGA,125646.600,3513.2272,N,08241.9347,W,1,03,3.85,187.3,M,-32.1,M,,*50'

sentence1Array = self.sentence1.split(',')
sentence2Array = self.sentence2.split(',')
# print self.sentence1
# print self.sentence2
if sentence1Array[0]=='$GPRMC':
self.timeUTC = sentence1Array[1][:-8]+':'+sentence1Array[1][-8:-6]+':'+sentence1Array[1][-6:-4]
self.latDeg = sentence1Array[3][:-7]
self.latMin = sentence1Array[3][-7:]
self.latHem = sentence1Array[4]
self.lonDeg = sentence1Array[5][:-7]
self.lonMin = sentence1Array[5][-7:]
self.lonHem = sentence1Array[6]
self.knots = sentence1Array[7]
self.haveGPRMC = True

if sentence1Array[0]=='$GPGGA':
self.fix = sentence1Array[6]
self.altitude = sentence1Array[9]
self.sats = sentence1Array[7]
self.haveGPGGA = True

if sentence2Array[0]=='$GPRMC':
self.timeUTC = sentence2Array[1][:-8]+':'+sentence2Array[1][-8:-6]+':'+sentence2Array[1][-6:-4]
self.latDeg = sentence2Array[3][:-7]
self.latMin = sentence2Array[3][-7:]
self.latHem = sentence2Array[4]
self.lonDeg = sentence2Array[5][:-7]
self.lonMin = sentence2Array[5][-7:]
self.lonHem = sentence2Array[6]
self.knots = sentence2Array[7]
self.haveGPRMC = True

if sentence2Array[0]=='$GPGGA':
self.fix = sentence2Array[6]
self.altitude = sentence2Array[9]
self.sats = sentence2Array[7]
self.haveGPGGA = True

#----------------------------------------------------------------
# Setup
haveFrameForBBBPin = 'P9_23' # From Arduino to BBB, has original Rx values.
GPIO.setup(haveFrameForBBBPin, GPIO.IN)

i2cBusForArduinoToBBB = smbus.SMBus(1)
smbusAddress = 0x50

pressureI2CAddress = 0x28
pressureI2CBus = Adafruit_I2C(pressureI2CAddress)

altitudeSensor = BMP085.BMP085()

BNO055I2CAddress = 0x29
bno = BNO055.BNO055(address=BNO055I2CAddress)
bno.begin()
dataFile = open('gpsdata.txt', 'w')

aileronServoPin = 'P8_13'
PWM.start(aileronServoPin,100,60.0)
elevatorServoPin = 'P9_42'
PWM.start(elevatorServoPin,100,60.0)
rudderServoPin = 'P9_14'
PWM.start(rudderServoPin,100,60.0)
throttleServoPin = 'P9_21'
PWM.start(throttleServoPin,100,60.0)

# Setup GPS
UART.setup('UART1')
gpsPort = serial.Serial('/dev/ttyO1', 9600)
gpsParser = gps()

#******************************************************************
#******************************************************************
# Main loop
# Loop once per transmitter frame
#******************************************************************
while True:

#******************************************************************
# Read receiver channel times from Arduino
#******************************************************************
# Wait for signal from Arduino
while GPIO.input(haveFrameForBBBPin) == False:
pass

readReceiverChannelsFromArduino()

#******************************************************************
# Read sensors
#******************************************************************
airspeedPressure = int(pressureI2CBus.readU16(0))
# print 'Airspeed pressure ',airspeedPressure

altitude = altitudeSensor.read_altitude()
# print 'altitude {0:0.2f} m'.format(altitude)
# print '\n'

gpsParser.readGPS()
# fixFromGPS = gpsParser.fix
if gpsParser.haveGPGGA & gpsParser.haveGPRMC:
# print 'fix: ', gpsParser.fix
if (gpsParser.fix != '0') & (gpsParser.sats > 4): # Have good GPS
# print 'Universal time: ', gpsParser.timeUTC
# print gpsParser.sats, 'satellites'
# print 'Latitude: ', gpsParser.latDeg, 'degrees ', gpsParser.latMin, 'minutes ', gpsParser.lat$
# print 'Longitude: ', gpsParser.lonDeg, 'degrees ', gpsParser.lonMin, 'minutes ', gpsParser.lon$
# print 'Speed: ', gpsParser.knots, ' knots'
# print 'GPS Altitude: ', gpsParser.altitude
################################################################
# print 'latitudeFloat = -( (float(gpsParser.latDeg) + (float(gpsParser.latMin)/60.0)) )'
# print 'float(gpsParser.latDeg) ',float(gpsParser.latDeg)
# print '(float(gpsParser.latMin)/60.0) ',(float(gpsParser.latMin)/60.0)

latitudeFloat = -( (float(gpsParser.latDeg) + (float(gpsParser.latMin)/60.0)) )
latitudeFloat = (float(gpsParser.latDeg) + (float(gpsParser.latMin)/60.0))
longitudeFloat = float(gpsParser.lonDeg) + (float(gpsParser.lonMin)/60.0)
# print 'Latitude Float: ', latitudeFloat
# print 'Longitude Float: ', longitudeFloat

latLonString = gpsParser.latMin+' '+gpsParser.lonMin+' '+'{0:0.2f}'.format(altitudeSensor.read_alt$
# print latLonString
dataFile.write(latLonString)
#################################################################
else: # do not have good GPS
pass

# Read BNO055 sensor
# Read the Euler angles for heading, roll, pitch (all in degrees).
heading, roll, pitch = bno.read_euler()
# Read the calibration status, 0=uncalibrated and 3=fully calibrated.
sys, gyro, accel, mag = bno.get_calibration_status()

# print('Heading={0:0.2F} Roll={1:0.2F} Pitch={2:0.2F}\tSys_cal={3} Gyro_cal={4} Accel_cal={5} Mag_cal={6$
# heading, roll, pitch, sys, gyro, accel, mag))
##################################################################
# Orientation as a quaternion:
#x,y,z,w = bno.read_quaterion()
# Sensor temperature in degrees Celsius:
#temp_c = bno.read_temp()
# Magnetometer data (in micro-Teslas):
#x,y,z = bno.read_magnetometer()
# Gyroscope data (in degrees per second):
#x,y,z = bno.read_gyroscope()
# Accelerometer data (in meters per second squared):
#x,y,z = bno.read_accelerometer()
# Linear acceleration data (i.e. acceleration from movement, not gravity--
# returned in meters per second squared):
#x,y,z = bno.read_linear_acceleration()
# Gravity acceleration data (i.e. acceleration just from gravity--returned
# in meters per second squared):
#x,y,z = bno.read_gravity()
#################################################################
setServos()

#******************************************************************
# Send a few things to BBB on the I2C bus
# so they can be sent to the data terminal on a TTL RS-232 bus
#******************************************************************
#------------------------------------------------------------------
def requestTransmissionToArduino():
i2cBusForArduinoToBBB.write_byte(0x50, int(gpsParser.fix) + 8)
i2cBusForArduinoToBBB.write_byte(0x50, sys)
i2cBusForArduinoToBBB.write_byte(0x50, gyro)
i2cBusForArduinoToBBB.write_byte(0x50, accel)
i2cBusForArduinoToBBB.write_byte(0x50, mag)

#------------------------------------------------------------------
# Send data for data terminal once per frame
requestTransmissionToArduino()

dataFile.close()

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Re: Using BBB without keyboard, screen, other computer

by williamm8 on Wed May 03, 2017 11:50 am

One last PS - in duplicating what you did in the post that contains the following:
"
Note the After= line.

And I enabled with the service with:
systemctl enable autopilot

The output was:
Created symlink from /etc/systemd/system/autopilot.service to /lib/systemd/system/autopilot.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/autopilot.service to /lib/systemd/system/autopilot.service.
"
I got the following result:

root@beaglebone:/lib/systemd/system# systemctl enable autopilot
Failed to issue method call: Invalid argument

changing to:
root@beaglebone:/lib/systemd/system# systemctl enable autopilot.service
root@beaglebone:/lib/systemd/system#

in other words, I had to say autopilot.service instead of just autopilot, and I did not get the verbose system response (the output was...) that you did. The terminal just came back with a normal prompt; everything behaved normally after that.

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Re: Using BBB without keyboard, screen, other computer

by drewfustini on Wed May 03, 2017 12:49 pm

williamm8 wrote:changing to:
root@beaglebone:/lib/systemd/system# systemctl enable autopilot.service
root@beaglebone:/lib/systemd/system#

in other words, I had to say autopilot.service instead of just autopilot, and I did not get the verbose system response (the output was...) that you did. The terminal just came back with a normal prompt; everything behaved normally after that.


I'd like to see the output of status:
systemctl status autopilot.service

It would be good to check if journalctl has any logs for the service:
journalctl -u autopilot.service

It also might help for debugging to remove the StandardOutput=null line from the autopilot.service unit file:
/lib/systemd/system/autopilot.service
[Unit]
Description=autopilot
After=generic-board-startup.service

[Service]
ExecStart=/root/autopilot.py

[Install]
WantedBy=multi-user.target
Alias=autopilot.service


Run this command to make the change active:
systemctl daemon-reload

I also I think the Alias= line may not be necessary. For example, I have this unit file enable-i2c-pins.service from a previous project:
[Unit]
Description=Enable I2C pins
After=generic-board-startup.service

[Service]
Type=simple
ExecStart=/usr/bin/enable-i2c-pins.sh

[Install]
WantedBy=multi-user.target


I can refer to both enable-i2c-pins and enable-i2c-pins.service ok:
root@beaglebone:~# systemctl is-enabled enable-i2c-pins
enabled
root@beaglebone:~# systemctl is-enabled enable-i2c-pins.service
enabled

drewfustini
 
Posts: 944
Joined: Sat Dec 26, 2015 1:19 pm

Re: Using BBB without keyboard, screen, other computer

by williamm8 on Thu May 04, 2017 9:27 am

I did a different experiment. I wrote the following python program "outrun.py (darn that automatic spelling. I think you'll figure out the name of the program any the time it's over)

#!/usr/bin/python

from time import sleep
import Adafruit_BBIO.GPIO as GPIO

testPin = 'P9_30'
GPIO.setup(testPin, GPIO.OUT)

while True:
GPIO.output(testPin, GPIO.LOW)
sleep(0.0001)
GPIO.output(testPin, GPIO.HIGH)
sleep(0.0001)

And the service to go with it:

[Unit]
Description=autorun
After=generic-board-startup.service

[Service]
ExecStart=/root/autorun.py
StandardOutput=null

[Install]
WantedBy=multi-user.target
Alias=autorun.service

I verify that autorun.py (well that's clever, paste it in from somewhere else!) is running by watching the testPin with a 'scope. When it's running, I get the expected square wave, when it's not running that pin is solid 0 V.

The overall behavior is exactly as I have experienced with the autopilot. When the BBB is booted with the USB cable, ssh'ed on an Apple terminal, I can run it, stop it, do 'start autorun.service' etc and it all starts and stops normally.

But the big test is unplugging the usb cable, and instead plugging in a 5V. power supply. autorun.py never runs. The 'scope stays flat lined (not the best choice of term for a seventy two year old, but it just came to mind).

This is about as simple as I can think of, and I have started to wonder if "boot" means the same thing to everyone in the linux and BBB world. I'm starting to suspect that it doesn't. This sort of problem has been biting me for sixty years, I do feel qualified in suggesting it.

Is there anything in the BBB that makes it "boot" whenever power is applied, without looking around for a terminal? What I want is for it to get up and running when it gets power, and perform my autopilot service. Then, of course, allow autopilot.py to run. No other attachments beside the (Adafruit) 5V. power supply.

I am beginning to suspect this sort of thing because all of the examples, in tutorials and you forum have done all their work looking at a terminal and keyboard. Everything seems to work fine that way, both on your end and mine.

So maybe it's time to get creative.

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Re: Using BBB without keyboard, screen, other computer

by williamm8 on Thu May 04, 2017 3:07 pm

Hold off on this problem for a little bit. The chmod 755 fixed my autorun test program, now it starts with nothing but the power supply plugged in. I'll go back and try it again with the autopilot program, but I am finished for the day. I'll send another post to let you know the result.

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Re: Using BBB without keyboard, screen, other computer

by williamm8 on Fri May 05, 2017 10:41 am

My assumption that if the whole system doesn't make servos rotate means that the BBB hasn't booted turns out to be wrong. I put my pin driving loop from autorun.py, watched pin 30 with a 'scope, plugged in the power supply (nothing else) and there were the pulses. So the autopilot.service mechanism is working after all.

The ball is in my court to troubleshoot what is hanging up. Thanks ever so much for promptly hanging in there with me. I'll make it work, and let you know what was wrong.

williamm8
 
Posts: 36
Joined: Wed Sep 11, 2013 4:07 pm

Please be positive and constructive with your questions and comments.