Controlar el Osciloscopio Hammer desde la PC
En el manual el osciloscopio dice que lleva una inicialización, pero eso debe haber sido con el firmware de fábrica cuando lo compraron, porque con el nuevo no hace falta. Se probó con el firmware original y no funcionó la comunicación así que se procedió a actualizar el firmware por una versión mas nueva. Luego de un par de pruebas se logró la comunicación con el mismo. La configuración del puerto serie se hace desde el osciloscopio mismo, en el menú->interfaz y ahí están las opciones del puerto, velocidad, bits, paridad, etc.
El manual con los comandos es el siguiente. Algo que no sale en el manual es que la Trama termina siempre con CR(Retorno de Carro - 0xd).
A continuación un programita de ejemplo hecho en python para poder comunicarse con el osciloscopio. Trae los datos de la actual pantalla y los grafica usando pylab.
1 #! /usr/bin/python
2 #coding=utf-8
3
4 from __future__ import division
5 import serial
6 import sys
7 import pylab
8 import time
9 import numpy
10
11
12 class communication(serial.Serial):
13 def __init__(self, *args, **kwargs):
14 #Asegura que el timeout tenga un valor rasonable
15 timeout = kwargs.get('timeout',0.1)
16 if timeout < 0.01: timeout = 0.1
17 kwargs['timeout'] = timeout
18 serial.Serial.__init__(self, *args, **kwargs)
19 self.buf = ''
20
21 def readline(self, timeout=1):
22 """timeout en segundos es el máximo tiempo que debe esperar para una trama completa"""
23 tries = 0
24 while 1:
25 self.buf += self.read(512)
26 pos = self.buf.find('\n')
27 if pos > 0:
28 line, self.buf = self.buf[:pos+1], self.buf[pos+1:]
29 return line
30 tries += 1
31 if tries * self.timeout > timeout:
32 break
33 line, self.buf = self.buf, ''
34 return line
35
36 def readlines(self, sizehint=None, timeout=1):
37 """Lee todas las tramas que hay disponibles. Aborta después del timeout
38 o cuando no hay mas datos."""
39 lines = []
40 while 1:
41 line = self.readline(timeout=timeout)
42 if line:
43 lines.append(line)
44 if not line:# or line[-1:] != '\n':
45 break
46 return lines
47
48 def send_cmd(self, dato):
49 if not dato.endswith('\n'):
50 dato += '\n'
51 self.write(dato)
52
53 def get_trace(self):
54 self.send_cmd(':TRAC:FORMAT ASCII')
55 time.sleep(0.1)
56 self.send_cmd(':TRAC:DATA?')
57 return self.readline(8).strip()
58
59 def get_time_scale(self):
60 s.send_cmd(':HOR:MAIN:SCAL?')
61 return s.readline().strip()
62
63 def get_amplitud_scale(self, channel="1"):
64 s.send_cmd(':CHAN%s:SCAL?' % channel)
65 return s.readline().strip()
66
67
68
69 if __name__=='__main__':
70 if len(sys.argv) <= 2:
71 print """
72 Uso: python %s /dev/ttyUSB0 filename""" % sys.argv[0]
73 sys.exit(0)
74 PORT = sys.argv[1]
75 BAUDRATE = 115200
76 s = communication(PORT, BAUDRATE)
77 s.flush()
78 data = s.get_trace()
79 fh_out = open("%s.txt" % sys.argv[2], 'w')
80 fh_out.write(data)
81 fh_out.close()
82 data = data.split(',')
83 data = numpy.asarray(data, numpy.float32)
84 cant_ptos = len(data)
85 axis_t = numpy.arange(cant_ptos)
86 time_scale = s.get_time_scale()
87 time_scale_float = float(time_scale)
88 #axis_t = axis_t * time_scale_float * 10
89 t_por_pto = (10*time_scale_float)/cant_ptos
90 axis_t = axis_t * t_por_pto
91
92 pylab.xlabel('%s Tiempo/Div' % time_scale)
93 pylab.ylabel('%s Voltage/Div' % s.get_amplitud_scale())
94 pylab.title('%s' % sys.argv[2])
95 pylab.grid(True)
96 pylab.plot(axis_t, data)
97 #print numpy.arange(0, 10*time_scale_float, time_scale_float)
98 pylab.xticks(numpy.arange(0, 10*time_scale_float, time_scale_float))
99 #pylab.xticks(numpy.arange(0, 10*s.get_time_scale(), s.get_time_scale()))
100 #pylab.yticks(numpy.arange(0, 8*float(s.get_amplitud_scale()), float(s.get_amplitud_scale())))
101 pylab.savefig('%s' % sys.argv[2])
102 #pylab.show()
103 print "Captura %s terminada" % sys.argv[2]
104 sys.exit(0)