教程:数据记录器#3 – 测量/图表/日志当前的树莓派

教程:数据记录器#3  - 测量/图表/日志当前的树莓派

教程:数据记录器#3 – 测量/图表/日志当前的树莓派

软件

IMG_7818由于目前在许多我们的SwitchDoc实验室的设计如此重要,我们决定建立一个基于树莓派数据记录器读了多少电流进入Arduino的基于发射器和使用这些信息来修改系统,以降低电流。本教程演示如何构建数据记录器。

第1部分:数据记录器介绍

第2部分:数据记录器硬件

第3部分:数据记录器的软件

数据记录仪包括运行数据记录Python软件,MySQL和MatPlotLib和Apache网络服务器一个树莓派3。本教程的这部分显示了如何安装的所有软件和有关DataLogger.py软件会谈。由于我们目前测量电流,我们使用的是  格罗夫INA3221 3通道电流/电压测量装置。

树莓丕软件安装

我们将需要安装以下三个主要的软件包。MySQL的/ phpMyAdmin的/ Apache Web服务器,apscheduler,MatPlotLib然后将数据记录的Python软件本身。

MySQL的/ phpMyAdmin的/阿帕奇

MySQL的是用来存储从数据记录器的软件的数据,以提供可用于以后的分析和绘图的数据库。phpMyAdmin的软件用于设置和控制MySQL数据库服务器,最后Apache是​​用来服务phpMyAdmin的网页和数据记录器的图形。

安装MySQL / phpMyAdmin的/阿帕奇-使用下面的优秀教程:   http://pimylifeup.com/raspberry-pi-mysql-phpmyadmin/

Apscheduler

apscheduler是用于从在不同的线程中运行的主Python程序内安排活动很好Python包。大约在另一个线程运行的任务像这样的好事,就是挂起的一个线程不会停止整个系统。只是,线程。

sudo pip install setuptools --upgrade 
sudo pip install apscheduler

MatPlotLib

MatPlotLib是制作使用类似于MATLIB对树莓派方法出版质量的情节一个Python库。您可以输出的格式,如PDF,后记,SVG和PNG。

安装以下软件包(这将需要相当长的时间)

$ sudo apt-get install libblas-dev        ## 1-2 minutes
$ sudo apt-get install liblapack-dev      ## 1-2 minutes
$ sudo apt-get install python-dev        ## Optional
$ sudo apt-get install libatlas-base-dev ## Optional speed up execution
$ sudo apt-get install gfortran           ## 2-3 minutes
$ sudo apt-get install python-setuptools  ## ?
$ sudo easy_install scipy                 ## 2-3 hours

$ sudo apt-get install python-matplotlib  ## 1 hour

数据记录器Python软件

要安装数据记录器软件,执行以下操作:

cd
git clone https://github.com/switchdoclabs/SDL_Pi_DataLogger.git

现在,你已经安装了所有必需的软件。

最后两件事情:

  1. 打开phpMyAdmin的,去到SQL标签和DataLogger.sql的内容复制到MySQL的框,然后点击“进入”,以建立数据库。
  2. 复制DataLogger.html到/ var / www / html等:
sudo cp DataLogger.html /var/www/html

现在,你准备好了。

数据记录器的主要软件模块

还有在数据记录器软件三大软件模块而承受一些解释。

调度软件

以下是如何定义往往是调度代码运行的常量。

 

#如何往往在几秒钟内样本数据
SampleTime = 0.5
#如何长秒的样本数据
LengthSample = 60000
常#如何生成秒图表
GraphRefresh = 10
#如何许多样品图
GraphSampleCount = 300

调度代码开始四个不同的工作,在单独的线程中运行。

  • READDATA – 读取INA3221并存储在MySQL的数据
  • buildGraph – 在构建MatPlotLib图,并将其复制到/ var / www / html等
  • killLogger – 的很长一段时间后杀死了记录软件
  • 嘀 – 打印出当前时间
    scheduler = BackgroundScheduler()
    scheduler.add_job(readData, 'interval', seconds=SampleTime)
    scheduler.add_job(buildGraph, 'interval', seconds=GraphRefresh)
    scheduler.add_job(killLogger, 'interval', seconds=LengthSample)
    scheduler.add_job(tick, 'interval', seconds=60)
    scheduler.start()
    scheduler.print_jobs()

 

该INA3221采样软件

调度调用数据采集软件的每个“SampleTime”0.5秒在上面的例子中。该INA3221被读取,然后将数据写入到MySQL数据库。

 

def readData():
    	print('readData - The time is: %s' % datetime.now())


  	print "------------------------------"
  	shuntvoltage1 = 0
  	busvoltage1   = 0
  	current_mA1   = 0
  	loadvoltage1  = 0


  	busvoltage1 = ina3221.getBusVoltage_V(LIPO_BATTERY_CHANNEL)
  	shuntvoltage1 = ina3221.getShuntVoltage_mV(LIPO_BATTERY_CHANNEL)
  	# minus is to get the "sense" right.   - means the battery is charging, + that it is discharging
  	current_mA1 = ina3221.getCurrent_mA(LIPO_BATTERY_CHANNEL)  

  	loadvoltage1 = busvoltage1 + (shuntvoltage1 / 1000)

        # set Label
	# myLabel = "LIPO_Battery"
        myLabel = ""  

  	print "(Channel 1) %s Bus Voltage 1: %3.2f V " % (myLabel, busvoltage1)
  	print "(Channel 1) %s Shunt Voltage 1: %3.2f mV " % (myLabel, shuntvoltage1)
  	print "(Channel 1) %s Load Voltage 1:  %3.2f V" % (myLabel, loadvoltage1)
  	print "(Channel 1) %s Current 1:  %3.2f mA" % (myLabel, current_mA1)
  	print

  	shuntvoltage2 = 0
  	busvoltage2 = 0
  	current_mA2 = 0
  	loadvoltage2 = 0

  	busvoltage2 = ina3221.getBusVoltage_V(SOLAR_CELL_CHANNEL)
  	shuntvoltage2 = ina3221.getShuntVoltage_mV(SOLAR_CELL_CHANNEL)
        # "-" removed for this demo program
  	current_mA2 = ina3221.getCurrent_mA(SOLAR_CELL_CHANNEL)
  	loadvoltage2 = busvoltage2 + (shuntvoltage2 / 1000)
  
        # set Label
	# myLabel = "Solar Cell"
        myLabel = ""  

  	print "(Channel 2) %s Bus Voltage 2:  %3.2f V " % (myLabel, busvoltage2)
  	print "(Channel 2) %s Shunt Voltage 2: %3.2f mV " % (myLabel, shuntvoltage2)
  	print "(Channel 2) %s Load Voltage 2:  %3.2f V" % (myLabel, loadvoltage2)
  	print "(Channel 2) %s Current 2:  %3.2f mA" % (myLabel, current_mA2)
  	print 

  	shuntvoltage3 = 0
  	busvoltage3 = 0
  	current_mA3 = 0
  	loadvoltage3 = 0

  	busvoltage3 = ina3221.getBusVoltage_V(OUTPUT_CHANNEL)
  	shuntvoltage3 = ina3221.getShuntVoltage_mV(OUTPUT_CHANNEL)
  	current_mA3 = ina3221.getCurrent_mA(OUTPUT_CHANNEL)
  	loadvoltage3 = busvoltage3 + (shuntvoltage3 / 1000)
        
	# set Label
	# myLabel = "Output"
        myLabel = ""  
  
  	print "(Channel 3) %s Bus Voltage 3:  %3.2f V " % (myLabel, busvoltage3)
  	print "(Channel 3) %s Shunt Voltage 3: %3.2f mV " % (myLabel, shuntvoltage3)
  	print "(Channel 3) %s Load Voltage 3:  %3.2f V" % (myLabel, loadvoltage3)
  	print "(Channel 3) %s Current 3:  %3.2f mA" % (myLabel, current_mA3)
  	print
	#
	# Now put the data in MySQL
	# 
        # Put record in MySQL

        print "writing SQLdata ";


        # write record
        deviceid = 0
        query = 'INSERT INTO '+tableName+('(timestamp, deviceid, channel1_load_voltage, channel1_current, channel2_load_voltage, channel2_current, channel3_load_voltage, channel3_current) VALUES(UTC_TIMESTAMP(),  %i,  %.3f, %.3f, %.3f, %.3f, %.3f, %.3f)' %( deviceid,  busvoltage1, current_mA1, busvoltage2, current_mA2, busvoltage3, current_mA3))
        print("query=%s" % query)

        cur.execute(query)	
	con.commit()
<\pre>

   不要忘了con.commit()结尾。否则,您的数据将神秘消失,因为READDATA()从主程序一个单独的线程运行。

该MatPlotLib图表软件

当由上述(在我们的示例代码,每10秒),调度程序调用,该图是从最后重建。这使得HTML页面来获得一个新的图的每个时间间隔。该图是由“GraphSampleCount”,300个样本在我们的例子中产生。

def buildGraph():
    		print('buildGraph - The time is: %s' % datetime.now())

		# open database
		con1 = mdb.connect('localhost', 'root', password, 'DataLogger' )
		# now we have to get the data, stuff it in the graph 

    		cursor = con1.cursor()

		query = '(SELECT timestamp, deviceid, channel1_load_voltage, channel1_current, channel2_load_voltage, channel2_current, channel3_load_voltage, channel3_current, id FROM '+tableName+' ORDER BY id DESC LIMIT '+ str(GraphSampleCount) + ') ORDER BY id ASC' 

		print "query=", query
		try:
			cursor.execute(query)
			result = cursor.fetchall()
		except:
			e=sys.exc_info()[0]
			print "Error: %s" % e


		print result[0]
		t = []   # time
		u = []   # channel 1 - Current 
		averageCurrent = 0.0
 		currentCount = 0
		for record in result:
			t.append(record[0])
			u.append(record[7])
			averageCurrent = averageCurrent+record[7]
			currentCount=currentCount+1

		averageCurrent = averageCurrent/currentCount
		
		print ("count of t=",len(t))

		fds = dates.date2num(t) # converted
		# matplotlib date format object
		hfmt = dates.DateFormatter('%H:%M:%S')
		#hfmt = dates.DateFormatter('%m/%d-%H')

		fig = pyplot.figure()
		fig.set_facecolor('white')
		ax = fig.add_subplot(111,axisbg = 'white')
		ax.vlines(fds, -200.0, 1000.0,colors='w')



		#ax.xaxis.set_major_locator(dates.MinuteLocator(interval=1))
		ax.xaxis.set_major_formatter(hfmt)
		ax.set_ylim(bottom = -200.0)
		pyplot.xticks(rotation='45')
		pyplot.subplots_adjust(bottom=.3)
		pylab.plot(t, u, color='r',label="Arduino Current",linestyle="-",marker=".")
		pylab.xlabel("Seconds")
		pylab.ylabel("Current mA")
		pylab.legend(loc='lower center')

		pylab.axis([min(t), max(t), 0, max(u)+20])
		pylab.figtext(.5, .05, ("Average Current %6.2fmA\n%s") %(averageCurrent, datetime.now()),fontsize=18,ha='center')

		pylab.grid(True)

		pyplot.show()
		pyplot.savefig("/var/www/html/DataLoggerGraph.png", facecolor=fig.get_facecolor())	



		cursor.close()       	 
		con1.close()

		fig.clf()
		pyplot.close()
		pylab.close()
		gc.collect()
		print "------Graph finished now"

当您使用此代码播放,请确保您在matplotlib.org网站每个命令查找,所以你知道你在做什么。这是一个有点神秘,至少可以说。

示例执行和结果

 

pi@RPi3:~/SDL_Pi_DataLogger $ sudo python DataLogger.py

Datalogger

Sample uses 0x40 and SunAirPlus board INA3221
 Will work with the INA3221 SwitchDoc Labs Breakout Board
Program Started at:2016-06-07 00:56:41

Jobstore default:
    readData (trigger: interval[0:00:00.500000], next run at: 2016-06-07 00:56:41 UTC)
    buildGraph (trigger: interval[0:00:10], next run at: 2016-06-07 00:56:51 UTC)
    tick (trigger: interval[0:01:00], next run at: 2016-06-07 00:57:41 UTC)
    killLogger (trigger: interval[16:40:00], next run at: 2016-06-07 17:36:41 UTC)
Press Ctrl+C to exit
buildGraph - The time is: 2016-06-07 00:56:41.355321
query= (SELECT timestamp, deviceid, channel1_load_voltage, channel1_current, channel2_load_voltage, channel2_current, channel3_load_voltage, channel3_current, id FROM WeatherLink ORDER BY id DESC LIMIT 300) ORDER BY id ASC
(datetime.datetime(2016, 6, 4, 17, 23, 26), 0L, 4.168, -39.6, 0.672, 0.0, 5.024, 9.6, 162901L)
('count of t=', 300)
readData - The time is: 2016-06-07 00:56:41.893182
------------------------------
(Channel 1)  Bus Voltage 1: 4.14 V 
(Channel 1)  Shunt Voltage 1: 1.00 mV 
(Channel 1)  Load Voltage 1:  4.15 V
(Channel 1)  Current 1:  10.00 mA

(Channel 2)  Bus Voltage 2:  0.00 V 
(Channel 2)  Shunt Voltage 2: 0.00 mV 
(Channel 2)  Load Voltage 2:  0.00 V
(Channel 2)  Current 2:  0.00 mA

(Channel 3)  Bus Voltage 3:  0.00 V 
(Channel 3)  Shunt Voltage 3: 0.00 mV 
(Channel 3)  Load Voltage 3:  0.00 V
(Channel 3)  Current 3:  0.00 mA

writing SQLdata 
query=INSERT INTO WeatherLink(timestamp, deviceid, channel1_load_voltage, channel1_current, channel2_load_voltage, channel2_current, channel3_load_voltage, channel3_current) VALUES(UTC_TIMESTAMP(),  0,  4.144, 10.000, 0.000, 0.000, 0.000, 0.000)
readData - The time is: 2016-06-07 00:56:42.409886
------------------------------
(Channel 1)  Bus Voltage 1: 4.02 V 
(Channel 1)  Shunt Voltage 1: 1.00 mV 
(Channel 1)  Load Voltage 1:  4.03 V
(Channel 1)  Current 1:  10.00 mA

(Channel 2)  Bus Voltage 2:  0.00 V 
(Channel 2)  Shunt Voltage 2: 0.00 mV 
(Channel 2)  Load Voltage 2:  0.00 V
(Channel 2)  Current 2:  0.00 mA

(Channel 3)  Bus Voltage 3:  0.00 V 
(Channel 3)  Shunt Voltage 3: 0.00 mV 
(Channel 3)  Load Voltage 3:  0.00 V
(Channel 3)  Current 3:  0.00 mA

writing SQLdata 
query=INSERT INTO WeatherLink(timestamp, deviceid, channel1_load_voltage, channel1_current, channel2_load_voltage, channel2_current, channel3_load_voltage, channel3_current) VALUES(UTC_TIMESTAMP(),  0,  4.024, 10.000, 0.000, 0.000, 0.000, 0.000)
No handlers could be found for logger "apscheduler.scheduler"
------Graph finished now
readData - The time is: 2016-06-07 00:56:43.349699
------------------------------
(Channel 1)  Bus Voltage 1: 3.82 V 
(Channel 1)  Shunt Voltage 1: 1.00 mV 
(Channel 1)  Load Voltage 1:  3.83 V
(Channel 1)  Current 1:  10.00 mA

(Channel 2)  Bus Voltage 2:  0.00 V 
(Channel 2)  Shunt Voltage 2: 0.00 mV 
(Channel 2)  Load Voltage 2:  0.00 V
(Channel 2)  Current 2:  0.00 mA

(Channel 3)  Bus Voltage 3:  0.00 V 
(Channel 3)  Shunt Voltage 3: 0.00 mV 
(Channel 3)  Load Voltage 3:  0.00 V
(Channel 3)  Current 3:  0.00 mA

writing SQLdata 
query=INSERT INTO WeatherLink(timestamp, deviceid, channel1_load_voltage, channel1_current, channel2_load_voltage, channel2_current, channel3_load_voltage, channel3_current) VALUES(UTC_TIMESTAMP(),  0,  3.824, 10.000, 0.000, 0.000, 0.000, 0.000)
readData - The time is: 2016-06-07 00:56:44.349705
------------------------------

这显示在连接的电流和电压的设备到通道1被测(DUT)。

这里是从所得的网页的示例曲线图。

Arduino的乌诺,然后Arduino的临迷你测试运行

Arduino UNO,然后Arduino Pro Mini 测试运行

结论

树莓丕数据记录器允许我们测量许多不同类型的变量,并使用相同的基本代码,并写入到用于进一步分析的数据库。使用自动刷新HTML页面可以让我们看到的数据,因为它不发生系统和网络过载很大。而且你可以很容易地修改HTML代码以及Python的数据记录代码。

 

使用Google自动编译自:http://www.switchdoc.com/2016/06/tutorial-datalogger-3-measuregraphlog-current-raspberry-pi/

标签