Having bought a new DC motor, I wanted to set it running via the Raspberry Pi and Arduino motor shield in a similar way to previous Robot arm efforts.
I set up the Raspberry Pi to connect to the Arduino via USB and a Hub. Power for the motor was taken via an external battery pack, as shown below:
(I've recently discovered Fritzing which is a great tool for generating schematics, I downloaded the Linux version from here http://fritzing.org/download/ )
The driver code is based on earlier Robot arm code. It reads a character from a terminal on the Raspberry Pi and sends that to the Ardunio:
# Read characters from stdin and send to Arduino via serial
import termios, fcntl, sys, os, serial
arduino = serial.Serial('/dev/ttyACM0')
fd = sys.stdin.fileno()
oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
try:
while 1: # This is a tight loop with high CPU
try:
c = sys.stdin.read(1)
# repr() : Return a string containing a printable
# representation of an object
arduino.write(c)
print "Read character from stdin", repr(c)
except IOError: pass
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
In this case on the Arduino, 'a' is interpreted as motor forward, 's' motor backward and space ' ' stop.
This all worked to begin with, I could start and stop the motor. However, after a period, normally less than a minute, I would lose response to any character input and had to reset the Arduino.
Investigating further it seemed like the USB connection had changed to a different tty, e.g. to /dev/ttyUSB0, and back.
I then looked in dmesg and saw the following:
usb disabled by hub (EMI?),
re-enabling…
EMI (ElectroMagnetic Interference)
The solution in this case was to remove the hub and run the USB direct to the Arduino. I'm speculating that the EMI from the motor starting and stopping was the cause of this, and reducing the cable length (and hub) was enough to lower the sensitivity beneath the threshold.
Wednesday, 8 June 2016
Thursday, 19 May 2016
Simple data transfer across local network
I wanted to play around with sending an receiving XML data from my laptop to a web server running on the Raspberry Pi. At the moment, I'm happy for all this to happen over my local network.
I decided to use webpy for its ease of development in allowing you to setup a simple server using Python. It can be installed with the following:
sudo easy_install web.py
The client was the Supermarket Planner app. For testing I put the code in the call to print. The first step was to convert the data collection to an XML string.
Because I used an ObservableCollection of SelectedMeal objects, this was simple using an XmlSerialiser:
SelectedMealCollection mealData;
XmlSerializer xs = new XmlSerializer(typeof(SelectedMealCollection));
string xml = "";
using (StringWriter writer = new StringWriter())
{
xs.Serialize(writer, mealData);
xml = writer.ToString();
}
Finally, I used an async method to create and call an HttpClient with the payload created above.
Note this creates the "data=" part of the payload from the KeyValuePair which needed to be trimmed by the server before using the XML.
I decided to use webpy for its ease of development in allowing you to setup a simple server using Python. It can be installed with the following:
sudo easy_install web.py
It's then very simple to write a web server that takes xml passed through a post method and saves it as a file:
import web, urllib
urls = (
'/index', 'index'
)
'/index', 'index'
)
class index:
def GET(self):
x = web.input()
return "<b>text=<b>"
def GET(self):
x = web.input()
return "<b>text=<b>"
def POST(self):
# This is the xml string passed from the client
x = web.data()
# Remove the header "data="
cleaned = x[5:]
# Write the XML string to file
filedir = '/home/pi/Scratch/test'
fout = open(filedir + '/test.xml', 'w')
# This is the xml string passed from the client
x = web.data()
# Remove the header "data="
cleaned = x[5:]
# Write the XML string to file
filedir = '/home/pi/Scratch/test'
fout = open(filedir + '/test.xml', 'w')
# Decode url characters
fout.write(urllib.unquote_plus(cleaned))
fout.close()
return x
fout.write(urllib.unquote_plus(cleaned))
fout.close()
return x
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
app = web.application(urls, globals())
app.run()
Because I used an ObservableCollection of SelectedMeal objects, this was simple using an XmlSerialiser:
SelectedMealCollection mealData;
XmlSerializer xs = new XmlSerializer(typeof(SelectedMealCollection));
string xml = "";
using (StringWriter writer = new StringWriter())
{
xs.Serialize(writer, mealData);
xml = writer.ToString();
}
Finally, I used an async method to create and call an HttpClient with the payload created above.
Note this creates the "data=" part of the payload from the KeyValuePair which needed to be trimmed by the server before using the XML.
private async Task<string> post( string payload )
{
using (var client = new HttpClient())
{
var postData = new KeyValuePair<string, string>[]
{
using (var client = new HttpClient())
{
var postData = new KeyValuePair<string, string>[]
{
new KeyValuePair<string, string>("data", payload),
};
new KeyValuePair<string, string>("data", payload),
};
var content = new FormUrlEncodedContent(postData);
var response = await client.PostAsync("http://192.168.0.2:8080/index", content);
if (!response.IsSuccessStatusCode)
{
var message = String.Format("Server returned HTTP error {0}: {1}.", (int)response.StatusCode, response.ReasonPhrase);
throw new InvalidOperationException(message);
}
{
var message = String.Format("Server returned HTTP error {0}: {1}.", (int)response.StatusCode, response.ReasonPhrase);
throw new InvalidOperationException(message);
}
var data = await response.Content.ReadAsStringAsync();
return data;
}
}
}
}
Thursday, 24 March 2016
Using a Servo
I've decided to see how much control I can add to the robot arm project so I bought a servo. This is a small motor that can be set to specific positions based on a signal. Such a device has 3 input lines, 2 for power and one for the signal.
First off, I wanted to use my new Ubuntu laptop to develop the Arduino code. Unfortunately, after installing the Arduino IDE and updating to version 1.6.7 I got the following error trying to upload the blink sketch:
avrdude: ser_open(): can't open device "/dev/ttyACM0": Permission denied
This is because in Ubuntu the current user isn't automatically given permission to the usb device. To grant permission I followed these steps
Now I was able to upload to the Ardunio I connected the servo, shown below
One thing I noticed, I had the servo plugged into SERVO_2 on the motor shield, conecting to SER1 resulted in the controller chip rapidly heating. Fortunately no damage was done.
I tried using the Sweep sketch with this and then the following
#include <Servo.h>
Servo servo;
void setup() {
// Attach the servo on pin 9 to the servo object
servo.attach(9);
}
void loop() {
servo.write(20);
delay(1000);
servo.write(160);
delay(1000);
}
A problem with this setup was the servo sometimes would jitter or stall. I suspect this was due to interference from the Arduniop and related perhaps to automation in the loop. I managed to reduce this almost entirely by removing the sleeps from the above sample and setting the angle via serial input:
#include <Servo.h>
Servo servo;
void setup() {
// Attach the servo on pin 9 to the servo object
servo.attach(9);
Serial.begin(19200);
Serial.println("Ready");
}
void loop() {
if (Serial.available())
{
char ch = Serial.read();
switch(ch)
{
case '1':
servo.write(40);
break;
case '2':
servo.write(60);
break;
case '3':
servo.write(80);
break;
case '4':
servo.write(100);
break;
case '5':
servo.write(120);
break;
}
}
}
I was also happy with this because I'll be controlling from the Raspberry Pi in a similar way to this in the future.
First off, I wanted to use my new Ubuntu laptop to develop the Arduino code. Unfortunately, after installing the Arduino IDE and updating to version 1.6.7 I got the following error trying to upload the blink sketch:
avrdude: ser_open(): can't open device "/dev/ttyACM0": Permission denied
This is because in Ubuntu the current user isn't automatically given permission to the usb device. To grant permission I followed these steps
- whoami (get username)
- sudo usermod -a -G dialout username : Modify user, add to dialout group (allows access to serial ports via files in /dev)
- sudo chmod a+rw /dev/ttyACM0 : give '+' all users 'a' read/write 'rw' access to /dev/ttyACM
Now I was able to upload to the Ardunio I connected the servo, shown below
- Brown : Groud
- Red : + 5v
- Yellow : S(ignal)
One thing I noticed, I had the servo plugged into SERVO_2 on the motor shield, conecting to SER1 resulted in the controller chip rapidly heating. Fortunately no damage was done.
I tried using the Sweep sketch with this and then the following
#include <Servo.h>
Servo servo;
void setup() {
// Attach the servo on pin 9 to the servo object
servo.attach(9);
}
void loop() {
servo.write(20);
delay(1000);
servo.write(160);
delay(1000);
}
A problem with this setup was the servo sometimes would jitter or stall. I suspect this was due to interference from the Arduniop and related perhaps to automation in the loop. I managed to reduce this almost entirely by removing the sleeps from the above sample and setting the angle via serial input:
#include <Servo.h>
Servo servo;
void setup() {
// Attach the servo on pin 9 to the servo object
servo.attach(9);
Serial.begin(19200);
Serial.println("Ready");
}
void loop() {
if (Serial.available())
{
char ch = Serial.read();
switch(ch)
{
case '1':
servo.write(40);
break;
case '2':
servo.write(60);
break;
case '3':
servo.write(80);
break;
case '4':
servo.write(100);
break;
case '5':
servo.write(120);
break;
}
}
}
I was also happy with this because I'll be controlling from the Raspberry Pi in a similar way to this in the future.
Thursday, 17 March 2016
Supermarket planner updates
I recently fixed a bug in the Supermarket planner which was caused by a problem with the binding of XML to the DataGrid. This is a good point to explain how I did the binding and the problems solved.
The XML containing the data looks like this:
<Meal name="Mushroom Omelette" type ="Vegetarian, Quick">
<Ingredients>
<Ingredient>Eggs</Ingredient>
<Ingredient>Mushrooms</Ingredient>
<Ingredient>Cheese</Ingredient>
<Ingredient>Salad</Ingredient>
</Ingredients>
</Meal>
<Meal name="Lamb Chops + Veg" type="">
<Ingredients>
<Ingredient>Lamb Chops</Ingredient>
<Ingredient>Brocolli</Ingredient>
<Ingredient>Courgette</Ingredient>
</Ingredients>
</Meal>
The grid looks like this. For each <Meal> element there is a row with text from the name attribute.
Double clicking on the row expands the grid to show the ingredients. You can also edit these
I used the XmlDataProvider for binding, this needed to be in the Windows.Resources to be accessible by the save event.
<Window.Resources>
<!-- Meal Data needs to be in the window resources so it can be accessed easily by the save event -->
<XmlDataProvider x:Name="Meals" x:Key="MealData" Source="./Data/SuperMarketDataMeals.xml" XPath="/SuperMarketData/Meals/Meal"/>
The DataGrid xaml itself is shown below
The DataGrid ItemsSource is set to {Binding} with DataContent from the {StaticResource MealData} defined earlier.
I use a DataGridTemplate column for the rows, using {Binding XPath=name} for the text.
For the expanded details grid I use a RowDetailsTemplate with its own DataGrid, ItemsSource now with {Binding XPath=Ingredients/Ingredient}
The double click handler simply changes the DetailsVisibility flag on the clicked row:
var row = (DataGridRow)sender;
row.DetailsVisibility = row.DetailsVisibility ==
System.Windows.Visibility.Collapsed ?
System.Windows.Visibility.Visible :
System.Windows.Visibility.Collapsed;
The bug was that when the row was minimised by double clicking, the grid details still contained the expanded row. This was manifested by dragging the next meal down across to the calendar grid. Instead of seeing that meal appear, the meal that had had its details shown was dropped instead. For example from the screen shot above, when the Omelette was minimised, dragging Lamb Chops for example would end up with the Omelette dropped.
To fix this, I needed to refresh the data grid when collapsing the details.
I needed to call CommitEdit first otherwise I would get a runtime exception "Refresh is not allowed during an AddNew or EditItem transaction"
if (row.DetailsVisibility == Visibility.Collapsed)
{
mealGrid.CommitEdit(DataGridEditingUnit.Row, true);
mealGrid.Items.Refresh();
}
The XML containing the data looks like this:
<Meal name="Mushroom Omelette" type ="Vegetarian, Quick">
<Ingredients>
<Ingredient>Eggs</Ingredient>
<Ingredient>Mushrooms</Ingredient>
<Ingredient>Cheese</Ingredient>
<Ingredient>Salad</Ingredient>
</Ingredients>
</Meal>
<Meal name="Lamb Chops + Veg" type="">
<Ingredients>
<Ingredient>Lamb Chops</Ingredient>
<Ingredient>Brocolli</Ingredient>
<Ingredient>Courgette</Ingredient>
</Ingredients>
</Meal>
The grid looks like this. For each <Meal> element there is a row with text from the name attribute.
Double clicking on the row expands the grid to show the ingredients. You can also edit these
I used the XmlDataProvider for binding, this needed to be in the Windows.Resources to be accessible by the save event.
<Window.Resources>
<!-- Meal Data needs to be in the window resources so it can be accessed easily by the save event -->
<XmlDataProvider x:Name="Meals" x:Key="MealData" Source="./Data/SuperMarketDataMeals.xml" XPath="/SuperMarketData/Meals/Meal"/>
The DataGrid xaml itself is shown below
I use a DataGridTemplate column for the rows, using {Binding XPath=name} for the text.
For the expanded details grid I use a RowDetailsTemplate with its own DataGrid, ItemsSource now with {Binding XPath=Ingredients/Ingredient}
The double click handler simply changes the DetailsVisibility flag on the clicked row:
var row = (DataGridRow)sender;
row.DetailsVisibility = row.DetailsVisibility ==
System.Windows.Visibility.Collapsed ?
System.Windows.Visibility.Visible :
System.Windows.Visibility.Collapsed;
The bug was that when the row was minimised by double clicking, the grid details still contained the expanded row. This was manifested by dragging the next meal down across to the calendar grid. Instead of seeing that meal appear, the meal that had had its details shown was dropped instead. For example from the screen shot above, when the Omelette was minimised, dragging Lamb Chops for example would end up with the Omelette dropped.
To fix this, I needed to refresh the data grid when collapsing the details.
I needed to call CommitEdit first otherwise I would get a runtime exception "Refresh is not allowed during an AddNew or EditItem transaction"
if (row.DetailsVisibility == Visibility.Collapsed)
{
mealGrid.CommitEdit(DataGridEditingUnit.Row, true);
mealGrid.Items.Refresh();
}
Wednesday, 27 January 2016
Remote Robot Arm, properly
Being able to control the Robot arm using a VNC client to connect to the Raspberry Pi is all very good but it's not a very elegant form of remote control. So, I decided to build an Android App on top of the work to date.
The App should have the following behaviour:
As this is only on the local network, I have control over the IP address assigned by the router. I hard-coded the host name and port on both Server and client.
On the robot-arm server it's only a matter of adding a few lines to enable TCP
import socket
TCP_IP = "192.168.0.12"
TCP_PORT = 5005
BUFFER_SIZE = 20 # Normally 1024, but we want a fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
and in the loop
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
# send the chractera to the arduinos
On the client side I created a new java.net.Socket and use a PrintWriter to send the control characters:
Socket socket = new Socket(hostName, port);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(ch);
Note that as this is an Android App, it's mandated that sockets are not opend on the main thread. It is very simple to extend AsyncTask and implement the doInBackground method.
Finally, we need to add Internet permission to the Android manifest file:
<uses-permission android:name="android.permission.INTERNET" />
Fortunately however, I found a solution in the PiStreaming project on GitHub https://github.com/waveform80/pistreaming.git
Following the install instructions and starting with python server.py I was able to view the stream from the camera with sub-second latency.
I use a WebView to show the video stream. In OnCreate it's configured with the following:
WebView piWebView = (WebView)findViewById(R.id.webview);
WebSettings webSettings = piWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
piWebView.setWebViewClient(new WebViewClient()
{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
return false;
}
});
piWebView.loadUrl("http://192.168.0.12:8082");
Java script must be enabled because the HTTP server uses it and the override shouldOverrideUrlLoading was added to stop the stream spawning a new web browser window.
To implement the required behaviour of the buttons, I used the OnTouchListener. The MotionEvents ACTION_DOWN and ACTION_UP capture the button press and release
There are a couple of problems here. I shouldn't need to create the TCP client each time and there is an intermittent but where the ACTION_UP pipeline doesn't fully make it to the robot, in this case the arm continues moving until I tap another button.
The video shows a demo of it in action. I'm using a low spec Android phone and hadn't connected all the motors but it gives an impression of how this works
The code for the Android App has been added to the git repository https://github.com/jscott7/Robot-Arm.git
The App should have the following behaviour:
- It should be able to display a stream from a web cam attached to the Raspberry PI.
- Control of the robot would be by pressing down on buttons on the screen. Releasing the button should stop the robot.
- At this point I only need to control this over the local network.
Remote Connection
Requirement 3 meant a simple TCP Client-Server model would suit me well.As this is only on the local network, I have control over the IP address assigned by the router. I hard-coded the host name and port on both Server and client.
On the robot-arm server it's only a matter of adding a few lines to enable TCP
import socket
TCP_IP = "192.168.0.12"
TCP_PORT = 5005
BUFFER_SIZE = 20 # Normally 1024, but we want a fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
and in the loop
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
# send the chractera to the arduinos
On the client side I created a new java.net.Socket and use a PrintWriter to send the control characters:
Socket socket = new Socket(hostName, port);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(ch);
Note that as this is an Android App, it's mandated that sockets are not opend on the main thread. It is very simple to extend AsyncTask and implement the doInBackground method.
Finally, we need to add Internet permission to the Android manifest file:
<uses-permission android:name="android.permission.INTERNET" />
Streaming a Video feed
Keeping things simple I thought an HTTP stream would be lightweight and easy to implement. It turns out most solutions described on the web introduce a large latency of several seconds.Fortunately however, I found a solution in the PiStreaming project on GitHub https://github.com/waveform80/pistreaming.git
Following the install instructions and starting with python server.py I was able to view the stream from the camera with sub-second latency.
Building the App
The app has two regions, the top half shows the video stream while the bottom has the buttons to control motionI use a WebView to show the video stream. In OnCreate it's configured with the following:
WebView piWebView = (WebView)findViewById(R.id.webview);
WebSettings webSettings = piWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
piWebView.setWebViewClient(new WebViewClient()
{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
return false;
}
});
piWebView.loadUrl("http://192.168.0.12:8082");
Java script must be enabled because the HTTP server uses it and the override shouldOverrideUrlLoading was added to stop the stream spawning a new web browser window.
To implement the required behaviour of the buttons, I used the OnTouchListener. The MotionEvents ACTION_DOWN and ACTION_UP capture the button press and release
m_upButton.setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
try
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
new TcpClient().execute("o");
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
new TcpClient().execute(" ");
}
}
catch(Exception ex)
{
return false;
}
return true;
}
});
@Override
public boolean onTouch(View v, MotionEvent event) {
try
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
new TcpClient().execute("o");
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
new TcpClient().execute(" ");
}
}
catch(Exception ex)
{
return false;
}
return true;
}
});
There are a couple of problems here. I shouldn't need to create the TCP client each time and there is an intermittent but where the ACTION_UP pipeline doesn't fully make it to the robot, in this case the arm continues moving until I tap another button.
Running the App to control the robot
On the Raspberry PI start both the web server and the robo-server. Then open the Robot Arm App. Touching the buttons cause the appropriate motors on the arm to move, releasing the button stops movement.The video shows a demo of it in action. I'm using a low spec Android phone and hadn't connected all the motors but it gives an impression of how this works
The code for the Android App has been added to the git repository https://github.com/jscott7/Robot-Arm.git
Tuesday, 26 January 2016
It was the best of Linux, the worst of Linux
Taking an update and upgrade on the Raspberry PI, I had a problem with unmet dependencies for raspberrypi-bootloader.
I ran the suggest fix of apt-get install -f and thought nothing more of it.
Unfortunately as it turns out there were problems....
I shutdown as always ( sudo shutdown now ) but when I tried to restart a couple of days later nothing.
I didn't get any response at all, connecting to the TV via HDMI yielded a blank screen but at least when I plugged the SD card into my laptop I did see all the files, so at least the card hadn't died.
This gave me an opportunity to copy over the files and re-image the card from the ISO that I still had from the original install.
I still use Win32DiskImage to setup the SD card, but as Windows only sees the boot partition I couldn't format it. The DiskManagement tool allowed me to format both, but not to remove the partitions.
Fortunately, there's a command line tool DISKPART that has much more control
So the worst of Linux; I've never had a machine be rendered unusable from an update, on any flavours of Windows
But the best of Linux; It took me just over an hour to restore the OS, then take the updates and have all my applications and development in precisely the state it was when things went wrong. Without multiple reboots.
I ran the suggest fix of apt-get install -f and thought nothing more of it.
Unfortunately as it turns out there were problems....
I shutdown as always ( sudo shutdown now ) but when I tried to restart a couple of days later nothing.
I didn't get any response at all, connecting to the TV via HDMI yielded a blank screen but at least when I plugged the SD card into my laptop I did see all the files, so at least the card hadn't died.
This gave me an opportunity to copy over the files and re-image the card from the ISO that I still had from the original install.
I still use Win32DiskImage to setup the SD card, but as Windows only sees the boot partition I couldn't format it. The DiskManagement tool allowed me to format both, but not to remove the partitions.
Fortunately, there's a command line tool DISKPART that has much more control
- Open an Administrator command prompt
- Run diskpart to open the tool
- Enter list disk to see which disk is the SD card
- Important point here, make sure you choose the right disk or you could wipe your OS
- If your SD is disk is #1 enter select disk 1
- Enter clean to format and clear all the partitions.
So the worst of Linux; I've never had a machine be rendered unusable from an update, on any flavours of Windows
But the best of Linux; It took me just over an hour to restore the OS, then take the updates and have all my applications and development in precisely the state it was when things went wrong. Without multiple reboots.
Monday, 14 December 2015
Keeping old data alive, building CERNLIB
Updated 28/4/1016 with additional link and clarification
Analysis of the data from the ZEUS experiment was performed using Fortran programs. These used the CERNLIB software libraries and data was stored in structures known as Ntuples.
I used Column-wise Ntuples, which are saved in a binary format. So when at the end of my Ph.D. analysis, I saved the old Ntuples to 11 CDs these became largely useless immediately I left Physics.
The Digital dark age therefore came to me sooner than I anticipated.
Fortunately with the source being made freely available and the necessary compilers being included in gcc I thought I'd have a try at building these on my Linux laptop.
At the time of this exercise I was running version 11.10 of Ubuntu.
Here are the steps I took, based on instructions from this page. One major issue I had with Lubuntu was that many of the dependency packages were not installed and I had to discover and apt-get them all. For this reason it's better not to try this on a cut down Linux.
-
Install gfortran (this is part of gcc, I have version 4.6.3)
-
Copy and unpack the CERNLIB binaries
-
Because I had a cut down Linux, I needed to build LessTif
-
Get xutils-dev package for imake
-
Set up the build environmentcd to the cern folder
~$ export CERN_ROOT=CERN_PATH/VERSION~$ export CVSCOSRC=$CERN_ROOT/src~$ mkdir $CERN_ROOT/build~$ cd $CERN_ROOT/build~$ export PATH=$CERN_ROOT/bin;$PATH
-
Update $CVSCOSRC/config/linuc.cf This file has some operating system specific information, I changed the following
-
#define hasgfortran
-
Change CcCmd to gcc
-
Check #define X11Includes
This needs to point to the location of the X Window headers, these can be installed usingsudo apt-get install xserver-xorg-dev
-
-
Run $CVSCOSRC/config/imake_boot to create the Makefile from the imake files
-
Run gmake bin/kuipc to build kuipc – this is built to /cern/new/bin
-
Add kuipc to path because this is required for the next build
-
Run gmake
A couple of other tips
link gmake to make using sudo ln -s /usr/bin/make /usr/bin/gmakeProblems and errors
There were a couple of errors in the main build that needed fixing:
#1
Conflicting types
for _XmDrawShadow /usr/local/include/xm/DrawP/h Previous declaration
is obsolete
Fix: Remove
_XmDrawShadow(); from iconwidget.c
#2
Pawlib/paw/cpaw/bugrep.c
L_cuserid undeclared.
Fix: It
should be in <stdio.h> but add #define L_cuserid 9 in the file
Finally, Liblapack3.a is required for PawX11
Subscribe to:
Posts (Atom)


