Collecting data with Arduino and Python

More
13 Aug 2012 21:01 #23118 by mcenter
I want to read a 0-5V signal at arbitrary time intervals and record the 0-5V information along with machine location, spindle speed, and time relative to first reading.

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;
    }
  }
}
I have a Python program that creates pins, polls the Arduino, and writes the data to a file:
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.

More
13 Aug 2012 23:17 #23128 by andypugh
The Mesa 7i87 might have worked for you, plugged into the 7i77 smart-serial port.

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.

More
14 Aug 2012 00:56 #23137 by mcenter
Yes, I studied Jeff Epler's Arduino project closely.
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.

More
14 Aug 2012 04:44 #23148 by cmorley
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

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.

More
14 Aug 2012 05:12 #23149 by mcenter
I am sorry. I didn't copy/paste all my python.
#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.

More
14 Aug 2012 08:03 #23152 by ArcEye
Hi

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.

More
14 Aug 2012 11:34 #23158 by VNR
andypugh:

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.

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)
Thanks you in advance,
VNR

Please Log in or Create an account to join the conversation.

More
14 Aug 2012 11:54 #23160 by andypugh
VNR wrote:

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

The Mesa firmware only sends/receives 8-bit data packets. All the protocol is handled at the Arduino and HAL ends.
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.

More
14 Aug 2012 15:29 #23169 by PCW
Its also possible to make the Arduino speak LBP at 1 Mbps so it can be a standard sserial remote with "discovery" and all that, so it would need no special support on the LinuxCNC end. 1 Mbps is pretty decent for real time and should be fine with 1-2 KHz servo thread rates. We're looking at adding some autobaud code to SSLBP (for our newer 4 and 10 Mbps capable cards) so 1M baud could be added to the search list

Please Log in or Create an account to join the conversation.

More
14 Aug 2012 16:56 #23172 by mcenter
I only need to read the spindle power in around 1 second intervals. I really don't care when I record a reading, as long as I know when a reading has been taken within .1 second, or so.

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).

File Attachment:

File Name: data_recorder.py
File Size:2 KB
Attachments:

Please Log in or Create an account to join the conversation.

Time to create page: 0.201 seconds
Powered by Kunena Forum