Collecting data with Arduino and Python
I have a 2-axis gantry using a Mesa 5i25 + 7i77 controlling Baldor 26M drives driving Baldor BSM90 servos. My spindle is a 3-HP Baldor 18H Vector drive. I am calling this incarnation the HawgScuff because I am using it for sanding research for the University of Arkansas (WPS!!)
I have the x and y axis working well with LinuxCNC. I need to add the spindle. I can configure the Baldor 18H like the 26M with 10V analog demand, but the induction motor is nowhere as responsive as the AC servo drive. I really don't need the (right word escapes me), for this incarnation. But, I plan to rotate the spindle 90 degrees after my research is complete, and use the machine for milling where rigid tapping would be nice.
The Baldor 18H can output a 0-5V signal repesenting the percentage of full load amperage. This value scales with the output torque of the motor. My plan is to sand a painted aluminum panel while changing speed, feed, and DOC parameters and recording location, spindle speed, and time. The panel can then be visually assessed for sanding parameter performance.
I decided against using the 7i77 for analog input. It was not clear to me how to do this, and the resolution seemed to be less than what I might need. So, I bought an Arduino Uno. I have written a sketch that waits for a request, then sends the analog signal value back:
int pos;
char buffer[128];
void setup()
{
Serial.begin(9600);
pos = 0;
for (int i = 0; i < sizeof(buffer); i++)
buffer[i] = 0;
}
void loop()
{
char c;
if (Serial.available() > 0) {
c = Serial.read();
if (c == '\n') {
buffer[pos] = 0;
if (strcmp(buffer,"RQ\n")) {
Serial.print(analogRead(A0));
pos = 0;
}
}
else {
buffer[pos] = c;
pos++;
if (pos >= sizeof(buffer))
pos = 0;
}
}
}
def pollArduino():
ser.write("RQ\n") #Request data
str = ser.readline()
if len(str) == 0:
print "Arduino is not responding!\n"
else:
return str
PORT = "/dev/ttyACM0"
#open serial for handshake
ser = serial.Serial(PORT, baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=1)
ser.open()
#generate a unique filename based on time
f = open('data_' + str(int(time.time()))+'.csv','w')
#write header
f.write('xpos, ypos, ain, sp, delT\n')
#create component pins for HAL
h = hal.component("datarecord")
# h.newpin("poll", hal.HAL_BIT, hal.HAL_IO) // NGC does not poll
h.newpin("record", hal.HAL_BIT, hal.HAL_IN)
h.newpin("xpos", hal.HAL_S32, hal.HAL_OUT)
h.newpin("ypos", hal.HAL_S32, hal.HAL_OUT)
h.newpin("sp", hal.HAL_S32, hal.HAL_OUT)
h.ready()
try:
basetime = time.time()
while 1:
delT = time.time() - basetime
if h['record'] == 1:
ain = pollArduino()
f.write(str( h['xpos']) +","+ str(h['ypos'])+','+str(ain)+','+str(h['sp'])+','+str(delT)+'\n')
time.sleep(1)
except (KeyboardInterrupt,):
raise SystemExit, 0
I can run the program in one terminal and halrun in another and everything works as expected. But, I am having problems integrating this with LinuxCNC.
When I "loadusr data_recorder.py" in my main .hal file and
net datarecord.record <= motion.digital-out-00
net datarecord.sp <= motion.spindle-speed-out
net datarecord.xpos <= halui.axis.0.pos-relative
net datarecord.ypos <= halui.axis.1.pos-relative
it loads the Python program and opens my data file, but it doesn't collect data when a M62 P00 is given in MDI, and only writes for the .csv file when linuxcnc closes. It seems like my python program is paused while linuxcnc is up.
I know my sketch and python program is not very sophisticated, perhaps I need to accomplish my task with a different method.
Does anyone have any suggestions?
Mark Center
Please Log in or Create an account to join the conversation.
However, the Arduino should work too. Have you seen: emergent.unpythonic.net/01198594294
I set up a UART on my Mesa card and have the Arduino talking 1Mb serial to a realtime HAL component. That was quite involved (custom Mesa firmware and changes to the Hostmot2 driver), but might also be an option.
Please Log in or Create an account to join the conversation.
I can read the Arduino and open and close my data file from my Python script in one terminal window, while using halrun to setp in another terminal window.
But, I can't get this to work through LinuxCNC.
It is like the userspace python script is not given any processing while LinuxCNC is running.
Mark
Please Log in or Create an account to join the conversation.
net datarecord.sp <= motion.spindle-speed-out
net datarecord.xpos <= halui.axis.0.pos-relative
net datarecord.ypos <= halui.axis.1.pos-relative
if that is your actual commands then you forgot to add signal names.
HAL net command creates signal names using the first name it sees.
try something like this:
net record-flag datarecord.record <= motion.digital-out-00
net spindle-speed datarecord.sp <= motion.spindle-speed-out
net x-rel-position datarecord.xpos <= halui.axis.0.pos-relative
net y-rel-position datarecord.ypos <= halui.axis.1.pos-relative
If that is not it post the complete python code. (I see no imports in the code you posted)
Chris M
Please Log in or Create an account to join the conversation.
#inialize serial port and open file
import serial
import hal
import time
def pollArduino():
ser.write("RQ\n") #Request data
str = ser.readline()
if len(str) == 0:
print "Arduino is not responding!\n"
else:
return str
PORT = "/dev/ttyACM0"
#open serial for handshake
ser = serial.Serial(PORT, baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=1)
ser.open()
#generate a unique filename based on time
f = open('data_' + str(int(time.time()))+'.csv','w')
#write header
f.write('xpos, ypos, ain, sp, delT\n')
#create component pins for HAL
h = hal.component("datarecord")
# h.newpin("poll", hal.HAL_BIT, hal.HAL_IO) // NGC does not poll
h.newpin("record", hal.HAL_BIT, hal.HAL_IN)
h.newpin("xpos", hal.HAL_S32, hal.HAL_OUT)
h.newpin("ypos", hal.HAL_S32, hal.HAL_OUT)
h.newpin("sp", hal.HAL_S32, hal.HAL_OUT)
h.ready()
try:
basetime = time.time()
while 1:
delT = time.time() - basetime
if h['record'] == 1:
ain = pollArduino()
f.write(str( h['xpos']) +","+ str(h['ypos'])+','+str(ain)+','+str(h['sp'])+','+str(delT)+'\n')
time.sleep(1)
except (KeyboardInterrupt,):
raise SystemExit, 0
The net commands were within my machine hal file. Tomorrow, I will add the signal names, remove the net commands from my machine hal file and create a separate hal, and add it to my ini file in the [HAL] section.
loadusr -W /home/linuxcnc/configs/hawgscuff/data_recorder.py
net record-flag datarecord.record <= motion.digital-out-00
net spindle-speed datarecord.sp <= motion.spindle-speed-out
net x-rel-position datarecord.xpos <= halui.axis.0.pos-relative
net y-rel-position datarecord.ypos <= halui.axis.1.pos-relative
waitusr datarecord
Thanks,
Mark
Please Log in or Create an account to join the conversation.
Its in C not python but some of the stuff in here may assist
www.linuxcnc.org/index.php/english/compo...=18&id=22562&limit=6
What is the purpose of the waitusr datarecord ?
regards
Please Log in or Create an account to join the conversation.
Is the protocol between the Mesa card and the Arduino handled by firmware in the Mesa card ? If it so, could be implemented a modbus/etercath/devicenet or other protocol in the firmware ? (may be using a 7i44 not a 7i77)The Mesa 7i87 might have worked for you, plugged into the 7i77 smart-serial port.
........
I set up a UART on my Mesa card and have the Arduino talking 1Mb serial to a realtime HAL component. That was quite involved (custom Mesa firmware and changes to the Hostmot2 driver), but might also be an option.
Thanks you in advance,
VNR
Please Log in or Create an account to join the conversation.
The Mesa firmware only sends/receives 8-bit data packets. All the protocol is handled at the Arduino and HAL ends.Is the protocol between the Mesa card and the Arduino handled by firmware in the Mesa card ? If it so, could be implemented a modbus/etercath/devicenet or other protocol in the firmware
I wrote a HAL comp for the job.
So, what you propose would be possible, but might be more easily done with the userspace serial driver.
Please Log in or Create an account to join the conversation.
Please Log in or Create an account to join the conversation.
Sometimes, I will use a screwdriver for a pry-bar. I always keep a Crescent wrench handy, although I have SAE and metric wrenches from very small to quite large with extra copies. The trick is realizing when you really should use a pry-bar, a box end wrench, or a gas hatchet and sledge hammer.
This is the HAL I used:
loadusr -Wn datarecord data_recorder.py
net record-flag datarecord.record <= motion.digital-out-00
net spindle-speed datarecord.sp <= motion.spindle-speed-out
net x-rel-position datarecord.xpos <= halui.axis.0.pos-relative
net y-rel-position datarecord.ypos <= halui.axis.1.pos-relative
A waitusr command would be superfluous.
Using M62 P00 followed by G1 X1 Y1 MDI commands (M62 doesn't take action until motion command), the signals change in the watch window, but datarecord pin values do not. (As seen in the attached watch window.
My Python script only writes the .csv header for the file, apparently h is never set to TRUE.
Thanks for all the input. I am still very much in the learning phase regarding linuxCNC, HAL, Python and C. I do plan to implement this as a comp later for a learning exercise. But, my summer is almost over, and I am behind schedule on my research. If I can't resolve these issues, I'll be out there with a clipboard and a stopwatch (think gas hatchet and sledge hammer).
Please Log in or Create an account to join the conversation.