├── .gitignore ├── .travis.yml ├── ExpEYES ├── Readme.md ├── expeyes-3.1.0.deb └── eyes-junior.zip ├── LICENSE ├── README.md ├── docs └── Hall-Effect-Sensor.png ├── experiments ├── 4channeldatalog │ └── 4channeldatalog.py ├── Coupled-Pendulum │ ├── coupledpendulum.md │ ├── coupledpendulum.py │ └── coupledpendulum2.py ├── GravityByTimeOfFlight │ └── GravityByTimeOfFlight.py ├── Lissajous-Figures │ └── Lissajous Figures.md ├── Measurements-using-expeyes │ └── Measurements-using-expeyes.py ├── Mechanics │ └── Spring-Oscillations.md ├── Voltammetry │ ├── Voltammetry.md │ └── voltammogram.py ├── Weather-Station │ ├── Weather-Data-Logger.py │ ├── weather-station-data.dat │ └── weather-station.md ├── control-PVS │ └── control-PVS.py └── velocityofsoundUsingPiezo │ └── velocityofsoundUsingPiezo.py ├── lang ├── Makefile ├── fr.po └── messages.pot ├── sensors ├── ATTINY85-MCU │ ├── ATTINY85.md │ └── Lissajous.py ├── AccelerometerADXL335 │ ├── ADXL335.md │ ├── Tilt-angle-GUI.py │ ├── Tilt-angle-measurement.py │ ├── acceleration-measurement.md │ ├── acceleration-xyz.py │ └── lissajous-accelerometer.py ├── Battery-Characteristics │ └── charging-discharging.py ├── Colour-Sensor │ └── IC-TCS3200D-SOP8.md ├── DC-motor-as-pickup-device │ └── dc-motor-pickup.py ├── Electronic-Compass │ └── 3-axis-magnetic-sensor-GY271.md ├── Gas-Sensors │ ├── MQ-4.md │ ├── MQ-4.py │ ├── MQ-6.md │ ├── MQ-6.py │ ├── MQ-7.md │ ├── MQ-7.py │ └── gas-sensors.py ├── Humidity-Sensor │ ├── HIH-4030.md │ ├── HS1101-measurement.py │ ├── HS1101.md │ ├── SY-HS-220.md │ └── humidity-HS1101-GUI.py ├── Infra-red-Object-Sensor │ ├── IR-object-sensor.py │ └── Object-sensor.md ├── Magnetic-Field-Sensors │ ├── Hall-Effect-Sensor.md │ ├── KY-003-sensor.md │ ├── KY-003-switching.py │ └── hall-effect-sensor.py ├── Photo-gate │ └── photo-gate.py ├── Piezoelectrie-Transducer │ ├── piezoelectric-transducer.md │ └── piezoelectric-transducer.py ├── Pressure-Sensor │ ├── PressureSensor.py │ ├── about-pressure-sensors.md │ └── barrometric-pressure-bmp180.py ├── Readme.md ├── Temp-Humidity-Sensor │ ├── DHT11-raspberrypi.py │ ├── DHT11.md │ └── reading-DHT11-trial.txt ├── Temperatur-Sensor │ ├── Temp-PT100-GUI.py │ ├── about-LM35.md │ ├── about-PT100.md │ └── temp-LM35-GUI.py ├── Test-Programs │ ├── Anemometer-Speed-Photogate.py │ └── Anemometer-Speed-magneticpickup.py └── Ultrasonic-Motion-Sensor │ ├── Getecho.py │ ├── Motion-Sensor-GUI.py │ ├── Motion-Sensor-SRF-05.md │ ├── motion-srf-two-sensors.py │ └── velocityofsound.py └── web-connectors ├── Auto-Tweet-Data ├── tweet-humidity-temp.py └── tweet.py └── Readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.bak 3 | *.pyc 4 | *.mo 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.6" 4 | - "2.7" 5 | - "3.2" 6 | - "3.3" 7 | - "3.4" 8 | # does not have headers provided, please ask https://launchpad.net/~pypy/+archive/ppa 9 | # maintainers to fix their pypy-dev package. 10 | #- "pypy" 11 | # command to install dependencies 12 | install: 13 | #- pip install . 14 | #- pip install -r requirements.txt 15 | # command to run tests 16 | script: nosetests 17 | 18 | notifications: 19 | slack: fossasia:3Liv2X68dnm0JlOfejqTEbAk 20 | -------------------------------------------------------------------------------- /ExpEYES/Readme.md: -------------------------------------------------------------------------------- 1 | ExpEYES Software 2 | 3 | Full software documentation at http://www.expeyes.in/software.html 4 | Github Repository: https://github.com/expeyes/expeyes-programs 5 | 6 | ExpEYES software is written in Python and it should run on any computer having Python interpreter (version > 2.7) and Python Serial library. It is included in the Debian and Ubuntu (version > 13.04) GNU/Linux distributions. Otherwise it can be installed from expeyes.deb file. 7 | For Ubuntu versions 10.04 to 12.10 you may use this deb file. 8 | 9 | 1. The expEYES Live ISO images for DVDs and USB pendrives 10 | 11 | The fastest way to get expEYES running on your PC is to boot your computer from a DVD or USB pendrive, prepared using the ISO image. The procedure to to this on MSWindows is explained here. Once you boot from the pen-drive, the Lubuntu desktop will appear. Start the expEYES program from the Applications->Science menu. Download the ISO images of the Live DVD. This ISO image is prepared from Lubuntu 14.04 and contains other educational resources also. 12 | 13 | 3. On Other GNU/Linux Distributions 14 | 15 | Download expeyes.zip and do the following: 16 | 17 | $unzip expeyes.zip 18 | 19 | $ cd eyes-junior 20 | 21 | $ sudo python croplus.py 22 | 23 | To use the device as a normal user, download the file to set the USB permissions by running. 24 | 25 | # sh postinst.sh 26 | 27 | 4. On MS Windows 28 | 29 | Since the programs are written in Python, the same source code works on GNU/Linux and Windows. You need to install Python Interpreter and the required libraries. The USB device appears as an RS232 connection to the software. The virtual COM port is established by the driver software for the USB to Serial converter MCP2200 30 | 31 | You need to install 32 | 33 | MCP2200 Driver 34 | Python Interpreter version 2.7xx 35 | Python Serial module 36 | Python TkInter module 37 | Python Imaging Library module 38 | Scipy and Numpy modules 39 | Then run the program croplus.py 40 | 41 | Windows version of the program 42 | A native Windows program is also available. It includes the main osciloscope application and severel experiments. More details are at http://www.expeyes.herobo.com/ 43 | -------------------------------------------------------------------------------- /ExpEYES/expeyes-3.1.0.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossasia/pslab-expeyes/dbffe73a7d2c4a897f97e6211b59e96a8b7464b9/ExpEYES/expeyes-3.1.0.deb -------------------------------------------------------------------------------- /ExpEYES/eyes-junior.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossasia/pslab-expeyes/dbffe73a7d2c4a897f97e6211b59e96a8b7464b9/ExpEYES/eyes-junior.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pocket Science Lab ExpEYES 2 | 3 | Repository for additional applications and sensor plugins to perform experiments with ExpEYES using Pocket Science Lab. 4 | 5 | [![Build Status](https://travis-ci.org/fossasia/pslab-expeyes.svg?branch=master)](https://travis-ci.org/fossasia/pslab-expeyes) 6 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/18fad6e7f96a49fe8ec531ad40149664)](https://www.codacy.com/app/mb/pslab-expeyes?utm_source=github.com&utm_medium=referral&utm_content=fossasia/pslab-expeyes&utm_campaign=Badge_Grade) 7 | [![Mailing List](https://img.shields.io/badge/Mailing%20List-FOSSASIA-blue.svg)](https://groups.google.com/forum/#!forum/pslab-fossasia) 8 | [![Gitter](https://badges.gitter.im/fossasia/pslab.svg)](https://gitter.im/fossasia/pslab?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 9 | [![Twitter Follow](https://img.shields.io/twitter/follow/pslabio.svg?style=social&label=Follow&maxAge=2592000?style=flat-square)](https://twitter.com/pslabio) 10 | 11 | This repository holds additional applications and sensor plugins to perform experiments with [ExpEYES](http://expeyes.in) using [Pocket Science Lab (PSLab)](https://pslab.io/). PSLab is a tiny pocket science lab that provides an array of equipment for doing science and engineering experiments. It can function like an oscilloscope, waveform generator, frequency counter, programmable voltage and current source and also as a data logger. ExpEYES is an Open Source Science experiments and data acquisition system for physics education and research. The website of PSLab is at https://pslab.io. 12 | 13 | ## Buy 14 | 15 | * You can get a Pocket Science Lab device from the [FOSSASIA Shop](https://fossasia.com). 16 | * More resellers are listed on the [PSLab website](https://pslab.io/shop/). 17 | 18 | ## Communication 19 | 20 | * The PSLab [chat channel is on Gitter](https://gitter.im/fossasia/pslab). 21 | * Please also join us on the [PSLab Mailing List](https://groups.google.com/forum/#!forum/pslab-fossasia). 22 | 23 | ## Installation 24 | 25 | ### 1. Install ExpEYES 26 | * You can install ExpEYES easily on any Linux machine. There are deb files available that we included in the repository. Please find details how to [install ExpEYES in the Readme.md](/ExpEYES/Readme.md). 27 | 28 | ### 2. Steps to install experiments 29 | * The software extension that are available in this repository in the folder /experiments can be installed as follows: 30 | * Copy the programs in home folder 31 | * ToDo: Create makefile for installing programs in ExpEYEs directory and make these experiments available in a dropdown menu of main GUI. 32 | 33 | ### 3. How to run experiments 34 | For Experiments various sensors and experimental setups are required. Typical steps are: 35 | * Connect ExpEYES to your PC/Laptop 36 | * Run Expeyes from Education Menue. The main ExpEYES GUI will popup. Check whether the device is detected. 37 | * Then close the ExpEYES GUI. 38 | * Open the terminal and run the program for e.g. 39 | 40 | `~ $ python coupledpendulum.py` 41 | 42 | ### 4. How to collect and save data 43 | * In order to make the experiments useful you need to collect and save data. 44 | * To Do: Describe here how to collect data and to save and use it. 45 | 46 | ## Compatible Sensors and Devices 47 | 48 | Below is a list of supported devices: 49 | 50 | 1. Accelerometer: Sensor Used: ADXL 335 - Three axis 51 | 2. Magnetic Field Sensor: KY 003, 3144 Hall Effect Sensor 52 | 3. Infra-red Object Sensord: Locally Made using IC LM-358N 53 | 4. Ultrasonic Position Sensor: SRF-05 HY, SRF-04 54 | 5. Temperature Sensor: PT-100 and LM-35 55 | 6. Humidity Sensor: DHT-11, HS-1101 56 | 7. Pressure- Barometric: BMP180 Digital sensor 57 | 8. Pressure: Pizzo Electric sensor 58 | 9. Gas Sensors 59 | * MQ-4 for Methane 60 | * MQ-6 for LPG 61 | * MQ-7 for Carbon Monoxide 62 | 10. Colour Sensor (in progress): IC-TCS3200D-SOP8 63 | 11. Anemometer- Wind Speed: Home-made sensor 64 | 12. Wind Direction: Home-made sensor 65 | 13. Rotatory Motion Sensor: DC Motor and a pick-up coil 66 | 14. Motion Sensor-Photo Gate: Photo Gate using Photo Diode 67 | 15. Other devices used as sensors 68 | * Solar Cells 69 | * Induction coil 70 | * Condensor mic 71 | * ATTINY-85 MCU used for sine wave generation 72 | * Raspberry Pi 2 Model B for stand-alone weather station 73 | * MicroHope 74 | 75 | ## Web Connectors 76 | It is possible to collect data and publish it automatically on the web on your own web application or on social networks like Twitter and Facebook. Find more info [web connectors here](/web-connectors/Readme.md). 77 | 78 | ## Blog Posts about PSLab and ExpEYES on FOSSASIA blog 79 | * [Sensor Plugins for ExpEYES](http://blog.fossasia.org/low-cost-laboratory-everyone-sensor-plug-ins-expeyes-measure-temperature-pressure-humidity-wind/) 80 | 81 | ## License 82 | This project is Free and Open Source software. The project us licensed under the [GPL v3](LICENSE). Copyright is owned by FOSSASIA. More details in the license files. 83 | -------------------------------------------------------------------------------- /docs/Hall-Effect-Sensor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossasia/pslab-expeyes/dbffe73a7d2c4a897f97e6211b59e96a8b7464b9/docs/Hall-Effect-Sensor.png -------------------------------------------------------------------------------- /experiments/4channeldatalog/4channeldatalog.py: -------------------------------------------------------------------------------- 1 | ''' 2 | expEYES program 3 | Author : Ajith Kumar B.P, bpajith@gmail.com, Praveen Patil for GSoC-16 4 | License : GNU GPL version 3 5 | ''' 6 | 7 | import gettext 8 | gettext.bindtextdomain("expeyes") 9 | gettext.textdomain('expeyes') 10 | _ = gettext.gettext 11 | 12 | import time, math, sys 13 | if sys.version_info.major==3: 14 | from tkinter import * 15 | else: 16 | from Tkinter import * 17 | 18 | sys.path=[".."] + sys.path 19 | 20 | import expeyes.eyesj as eyes 21 | import expeyes.eyeplot as eyeplot 22 | import expeyes.eyemath as eyemath 23 | 24 | NCHAN = 5 25 | WIDTH = 600 # width of drawing canvas 26 | HEIGHT = 400 # height 27 | 28 | class Logger: 29 | chan = [1,2,3,4,5] 30 | tv = [ [], [] ] # Lists for Time & Voltage 31 | MAXTIME = 10 # Maximum time, user can set 32 | TIMER = 500 33 | MINY = -5 # could be 0 34 | MAXY = 5.0 35 | start_time = None 36 | running = False 37 | 38 | def __init__(self): 39 | self.chinfo = [] 40 | for ch in range(NCHAN): 41 | self.chinfo.append([False, [[],[]], 0]) # Active, Data, Start Time 42 | 43 | def start(self): 44 | self.running = False # Assume no channel is selected 45 | for ch in range(NCHAN): 46 | self.chinfo[ch][1] = [ [], [] ] # Clear old data 47 | if CH[ch].get() == 1: 48 | self.chinfo[ch][0] = True 49 | self.running = True 50 | else: 51 | self.chinfo[ch][0] = False 52 | try: 53 | self.MAXTIME = int(DURATION.get()) 54 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('Volt')) 55 | self.TIMER = int(TGAP.get()) 56 | for k in range(4): CB[k].config(state = DISABLED) 57 | Total.config(state=DISABLED) 58 | Dur.config(state=DISABLED) 59 | self.msg(_('Starting the Measurement')) 60 | root.after(self.TIMER, self.update) 61 | except: 62 | self.msg(_('Failed to Start Measurement')) 63 | pass 64 | 65 | def stop(self): 66 | for k in range(5): CB[k].config(state = NORMAL) 67 | Total.config(state=NORMAL) 68 | Dur.config(state=NORMAL) 69 | self.running = False 70 | 71 | def update(self): 72 | if self.running == False: 73 | return 74 | g.delete_lines() 75 | for ch in range(NCHAN): 76 | if self.chinfo[ch][0] == True: 77 | t,v = p.get_voltage_time(self.chan[ch]) 78 | if len(self.chinfo[ch][1][0]) == 0: 79 | self.chinfo[ch][2] = t 80 | elapsed = 0 81 | else: 82 | elapsed = t - self.chinfo[ch][2] 83 | self.chinfo[ch][1][0].append(elapsed) 84 | self.chinfo[ch][1][1].append(v) 85 | if len(self.chinfo[ch][1][0]) >= 2: 86 | g.line(self.chinfo[ch][1][0], self.chinfo[ch][1][1],ch, smooth=True) 87 | try: 88 | self.MAXTIME = int(DURATION.get()) 89 | self.TIMER = int(TGAP.get()) 90 | except: 91 | pass 92 | if elapsed > self.MAXTIME: 93 | for k in range(5): CB[k].config(state = NORMAL) 94 | Total.config(state=NORMAL) 95 | Dur.config(state=NORMAL) 96 | self.running = False 97 | return 98 | root.after(self.TIMER, self.update) 99 | 100 | def save(self): 101 | try: 102 | fn = filename.get() 103 | except: 104 | fn = 'logger.dat' 105 | f = open(fn, 'w') 106 | for ch in range(NCHAN): 107 | if self.chinfo[ch][0] == True: 108 | size = len(self.chinfo[ch][1][0]) 109 | for k in range(size): 110 | s = '%5.3f %5.3f\n'%(self.chinfo[ch][1][0][k], self.chinfo[ch][1][1][k]) 111 | f.write(s) 112 | f.write('\n') 113 | msg.config(text = _('Data Saved')) 114 | 115 | def clear(self): 116 | if self.running == True: 117 | return 118 | for ch in range(NCHAN): 119 | self.chinfo[ch][1] = [ [], [] ] 120 | g.delete_lines() 121 | 122 | def msg(self,s): 123 | msgwin.config(text=s) 124 | 125 | 126 | p = eyes.open() 127 | p.disable_actions() 128 | root = Tk() 129 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 130 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) # make plot objects using draw.disp 131 | log = Logger() 132 | 133 | cf = Frame(root, width = WIDTH, height = 10) 134 | cf.pack(side=TOP, fill = BOTH, expand = 1) 135 | 136 | CB = [0]*NCHAN 137 | CH = [IntVar(), IntVar(), IntVar(), IntVar(), IntVar()] 138 | for k in range(NCHAN): 139 | CB[k] = Checkbutton(cf,text ='A%1d'%(k+1), variable=CH[k], fg = 'black') 140 | CB[k].pack(side=LEFT, anchor = SW) 141 | CH[k].set(0) 142 | if k == 2: CB[k].config(text=_('IN1')) 143 | if k == 3: CB[k].config(text=_('IN2')) 144 | if k == 4: CB[k].config(text=_('SEN')) 145 | CH[0].set(1) 146 | 147 | b3 = Label(cf, text = _('Read Every')) 148 | b3.pack(side = LEFT, anchor = SW) 149 | TGAP = StringVar() 150 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 151 | TGAP.set('500') 152 | Dur.pack(side = LEFT, anchor = SW) 153 | b3 = Label(cf, text = _('mS,')) 154 | b3.pack(side = LEFT, anchor = SW) 155 | b3 = Label(cf, text = _('for total')) 156 | b3.pack(side = LEFT, anchor = SW) 157 | DURATION = StringVar() 158 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 159 | DURATION.set('100') 160 | Total.pack(side = LEFT, anchor = SW) 161 | b3 = Label(cf, text = _('Seconds')) 162 | b3.pack(side = LEFT, anchor = SW) 163 | b1 = Button(cf, text = _('START'), command = log.start) 164 | b1.pack(side = LEFT, anchor = N) 165 | b1 = Button(cf, text = _('STOP'), command = log.stop) 166 | b1.pack(side = LEFT, anchor = N) 167 | b4 = Button(cf, text = _('CLEAR'), command = log.clear) 168 | b4.pack(side = LEFT, anchor = N) 169 | 170 | cf = Frame(root, width = WIDTH, height = 10) 171 | cf.pack(side=TOP, fill = BOTH, expand = 1) 172 | b3 = Button(cf, text = _('SAVE to'), command = log.save) 173 | b3.pack(side = LEFT, anchor = N) 174 | filename = StringVar() 175 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 176 | filename.set('logger.dat') 177 | e1.pack(side = LEFT) 178 | 179 | b5 = Button(cf, text = _('QUIT'), command = sys.exit) 180 | b5.pack(side = RIGHT, anchor = N) 181 | 182 | mf = Frame(root, width = WIDTH, height = 10) 183 | mf.pack(side=TOP, fill = BOTH, expand = 1) 184 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 185 | msgwin.pack(side=LEFT) 186 | 187 | root.title(_('EYES-Junior: Four Channel Data Logger')) 188 | root.mainloop() 189 | -------------------------------------------------------------------------------- /experiments/Coupled-Pendulum/coupledpendulum.md: -------------------------------------------------------------------------------- 1 | 2 | Coupled Pendulums 3 | 4 | Oscillations of Coupled pendula is an interesting phenomenon in Physics. 5 | A one dimensional oscillation can be thought of as an object moving back and forth about an equilibrium position. In this experiment we consider the oscillating system of two coupled pendulums (they are coupled by springs). 6 | 7 | If we connect two identical pendulums with a spring, one is held by hand, and another is deviated aside so the spring is stressed and then both the pendulums are released. How they will move? Intuitively it seems that the still pendulum will set into the motion under action of a spring and after a while both pendulums will oscillate chaotically. Actually Something very interesting happens. 8 | The pendulums will periodically exchange the energy and stop by turns. 9 | 10 | In this experiment we can study this periodic “swapping” of energy in two identical pendulums coupled with a spring. If we swing one pendulum, then the oscillatory energy will begin to be transferred to other pendulum. After the end of this process the energy will be transferred in the opposite direction. Thus, there is a periodic exchange of energy between the pendulums. As a result the amplitude of oscillation of every pendulum is periodically changed. When one pendulum oscillate with the maximal amplitude the other one is still. 11 | Here is the experimental set-up…. 12 | Pendulums are fixed to DC motors (we are using these as pick-up device as rotational motion sensors are very costly). The emf generated is amplified amplifier in ExpEYES and is fed to channels A1 and A2. Using voltage capture functions plots are obtained. 13 | 14 | ![Image of cp1](http://www.gnovi.in/files/2014/07/cp1-17jiaqb.jpg) 15 | The waveforms generated using DC motors after amplification… 16 | 17 | Figure 1 shows waveform for the first pendulum and Figure 2 shows waveform for the second pendulum. In figure 3 both waveforms are plotted together. 18 | 19 | ![Image of coupled-pendula1](http://www.gnovi.in/files/2014/07/coupled-pendula1-y3ige5.png) 20 | ![Image of coupled-pendula2](http://www.gnovi.in/files/2014/07/coupled-pendula2-1e33ttg.png) 21 | 22 | 23 | 24 | Using subplot function of matplotlib the following figure is obtained. Here one can easily compare the waveforms of two pendulums. 25 | 26 | ![Image of coupled-pendula3](http://www.gnovi.in/files/2014/07/coupled-pendula3-1dads31.png) 27 | 28 | The waveforms show beats as theoretically expected…. 29 | This experiment can be performed by oscillating pendulums in different ways… 30 | 31 | Both oscillating in phase 32 | Both oscillating out of phase 33 | One at rest and other oscillating 34 | 35 | When both the pendulums oscillate in phase 36 | 37 | ![Image of coupled-pendula4](http://www.gnovi.in/files/2014/07/coupledinphase-132mfdp.png) 38 | 39 | When pendulums oscillate out of phase 40 | 41 | ![Image of coupled-pendula5](http://www.gnovi.in/files/2014/07/coupledoutofphase-1s7ol9d.png) 42 | 43 | 44 | When one pendulum is at rest while the other is given oscillations 45 | 46 | ![Image of coupled-pendula6](http://www.gnovi.in/files/2014/07/coupled-pendula3-1dads31.png) 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /experiments/Coupled-Pendulum/coupledpendulum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | expEYES program 3 | Developed as a part of GSoC- project 4 | License : GNU GPL version 3 5 | 6 | Program to plot oscillations of TWO coupled pendulums in real-time 7 | 8 | ''' 9 | import gettext 10 | gettext.bindtextdomain("expeyes") 11 | gettext.textdomain('expeyes') 12 | _ = gettext.gettext 13 | 14 | 15 | import time, math, sys 16 | if sys.version_info.major==3: 17 | from tkinter import * 18 | else: 19 | from Tkinter import * 20 | 21 | sys.path=[".."] + sys.path 22 | 23 | import expeyes.eyesj as eyes 24 | import expeyes.eyeplot as eyeplot 25 | import expeyes.eyemath as eyemath 26 | 27 | WIDTH = 600 # width of drawing canvas 28 | HEIGHT = 400 # height 29 | 30 | class Pend: 31 | tv = [ [], [], [] ] # Three Lists for Readings time, v1 and v2 32 | TIMER = 5 # Time interval between reads 33 | MINY = -5 # Voltage range 34 | MAXY = 5 35 | running = False 36 | MAXTIME = 10 37 | 38 | def xmgrace(self): 39 | if self.running == True: 40 | return 41 | p.grace([self.tv]) 42 | 43 | def start(self): 44 | self.running = True 45 | self.index = 0 46 | self.tv = [ [], [], [] ] 47 | try: 48 | self.MAXTIME = int(DURATION.get()) 49 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('Volt')) 50 | Dur.config(state=DISABLED) 51 | self.msg(_('Starting the Measurements')) 52 | root.after(self.TIMER, self.update) 53 | except: 54 | self.msg(_('Failed to Start')) 55 | 56 | def stop(self): 57 | self.running = False 58 | Dur.config(state=NORMAL) 59 | self.msg(_('User Stopped the measurements')) 60 | 61 | def update(self): 62 | if self.running == False: 63 | return 64 | t,v = p.get_voltage_time(1) # Read A1 65 | v2 = p.get_voltage(2) 66 | if len(self.tv[0]) == 0: 67 | self.start_time = t 68 | elapsed = 0 69 | else: 70 | elapsed = t - self.start_time 71 | self.tv[0].append(elapsed) 72 | self.tv[1].append(v) 73 | self.tv[2].append(v2) 74 | if len(self.tv[0]) >= 2: 75 | g.delete_lines() 76 | g.line(self.tv[0], self.tv[1]) 77 | g.line(self.tv[0], self.tv[2],1) 78 | if elapsed > self.MAXTIME: 79 | self.running = False 80 | Dur.config(state=NORMAL) 81 | self.msg(_('Completed the Measurements')) 82 | return 83 | root.after(self.TIMER, self.update) 84 | 85 | def save(self): 86 | try: 87 | fn = filename.get() 88 | except: 89 | fn = 'coupledpend.dat' 90 | p.save([self.tv],fn) 91 | self.msg(_('Data saved to %s')%fn) 92 | 93 | def clear(self): 94 | if self.running == True: 95 | return 96 | self.tv = [ [], [], [] ] 97 | g.delete_lines() 98 | self.msg(_('Cleared Data and Trace')) 99 | 100 | def msg(self,s, col = 'blue'): 101 | msgwin.config(text=s, fg=col) 102 | 103 | p = eyes.open() 104 | p.disable_actions() 105 | root = Tk() 106 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 107 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) # make plot objects using draw.disp 108 | pen = Pend() 109 | 110 | cf = Frame(root, width = WIDTH, height = 10) 111 | cf.pack(side=TOP, fill = BOTH, expand = 1) 112 | 113 | 114 | b3 = Label(cf, text = _('Digitize for')) 115 | b3.pack(side = LEFT, anchor = SW) 116 | DURATION = StringVar() 117 | Dur =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 118 | DURATION.set('10') 119 | Dur.pack(side = LEFT, anchor = SW) 120 | b3 = Label(cf, text = _('Seconds.')) 121 | b3.pack(side = LEFT, anchor = SW) 122 | 123 | cf = Frame(root, width = WIDTH, height = 10) 124 | cf.pack(side=TOP, fill = BOTH, expand = 1) 125 | b1 = Button(cf, text = _('START'), command = pen.start) 126 | b1.pack(side = LEFT, anchor = N) 127 | b1 = Button(cf, text = _('STOP'), command = pen.stop) 128 | b1.pack(side = LEFT, anchor = N) 129 | b4 = Button(cf, text = _('CLEAR'), command = pen.clear) 130 | b4.pack(side = LEFT, anchor = N) 131 | b1 = Button(cf, text = _('Xmgrace'), command = pen.xmgrace) 132 | b1.pack(side = LEFT, anchor = N) 133 | b3 = Button(cf, text = _('SAVE to'), command = pen.save) 134 | b3.pack(side = LEFT, anchor = N) 135 | filename = StringVar() 136 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 137 | filename.set('coupledpend.dat') 138 | e1.pack(side = LEFT) 139 | b5 = Button(cf, text = _('QUIT'), command = sys.exit) 140 | b5.pack(side = RIGHT, anchor = N) 141 | 142 | mf = Frame(root, width = WIDTH, height = 10) 143 | mf.pack(side=TOP) 144 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 145 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 146 | 147 | 148 | eyeplot.pop_image('pics/image-name.png', _('Coupled Pendulum Oscillations')) # save the image in the same directory as of the program 149 | root.title(_('Oscillations of Coupled Pendulums')) 150 | root.mainloop() 151 | -------------------------------------------------------------------------------- /experiments/Coupled-Pendulum/coupledpendulum2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GSoC ExpEYES program 3 | License : GNU GPL version 3 4 | Program to study oscillations of coupled pendulum. Store readings and then plot. 5 | connect motor of pendulum1 to IN and GND, OUT to A1 6 | Connect motor of pendulum2 to IN and GND of another ExpEYES box. Connect OUT to Channel A2 of the first ExpEYES box. 7 | Note: Second ExpEYES box must be connected and detected by CROPLUS program, then run coupledpendula.py so that first ExpEYES box will be detected. 8 | This experiment can be done in three different ways 9 | 1. both the pendula oscillating in-phase 10 | 2. Both the pendula oscillating out-of-phase 11 | 3. One pendulum at rest while other is set in to oscillations. 12 | ''' 13 | from __future__ import print_function 14 | import gettext 15 | gettext.bindtextdomain("expeyes") 16 | gettext.textdomain('expeyes') 17 | _ = gettext.gettext 18 | from pylab import * 19 | import expeyes.eyesj, time 20 | p = expeyes.eyesj.open() 21 | DURATION = 15 22 | ta = [] 23 | tb = [] 24 | va = [] 25 | vb = [] 26 | f = open('pend_wave.dat','w') 27 | start = p.get_voltage_time(1)[0] 28 | start2 = p.get_voltage_time(2)[0] 29 | while 1: 30 | res = p.get_voltage_time(1) 31 | tm = res[0] - start # elapsed time 32 | ta.append(tm) 33 | va.append(res[1]) 34 | res2 = p.get_voltage_time(2) 35 | tm2 = res2[0] - start # elapsed time 36 | tb.append(tm2) 37 | vb.append(res2[1]) 38 | ss = '%6.3f %6.3f %6.3f %6.3f'%(tm,res[1],tm2,res2[1]) 39 | print (ss) 40 | f.write(ss+'\n') 41 | if tm > DURATION: 42 | break 43 | subplot(3,1,1) 44 | plot(ta,va,'r') #position Plot 45 | title('Pendulum - 1') 46 | xlabel('Time') 47 | ylabel('Displacement') 48 | subplot(3,1,2) 49 | plot(tb,vb, 'b') 50 | title('Pendulum - 2') 51 | xlabel('Time') 52 | ylabel('Displacement') 53 | subplot(3,1,3) 54 | plot(ta,va,'r', tb,vb, 'b') 55 | title('Coupled Pendula') 56 | xlabel('Time') 57 | ylabel('Displacement') 58 | plt.tight_layout() #this function from matplotlib provides spacing between subgraphs 59 | show() 60 | ''' 61 | # This code can be used to have plots in separate figures 62 | figure(1) 63 | plot(ta,va) 64 | figure(2) 65 | plot(tb,vb) 66 | figure(3) 67 | plot(ta,va, tb,vb) 68 | show() 69 | ''' 70 | -------------------------------------------------------------------------------- /experiments/GravityByTimeOfFlight/GravityByTimeOfFlight.py: -------------------------------------------------------------------------------- 1 | ''' 2 | ExpEYES program developed as a part of GSoC-2016 project 3 | Project Tilte: 4 | Mentor Organization:FOSSASIA 5 | License : GNU GPL version 3 6 | ''' 7 | 8 | from __future__ import print_function 9 | import gettext, sys 10 | gettext.bindtextdomain("expeyes") 11 | gettext.textdomain('expeyes') 12 | _ = gettext.gettext 13 | 14 | import time, math, sys 15 | if sys.version_info.major==3: 16 | from tkinter import * 17 | else: 18 | from Tkinter import * 19 | 20 | sys.path=[".."] + sys.path 21 | from expeyes import eyeplot 22 | 23 | import expeyes.eyesj 24 | p= expeyes.eyesj.open() 25 | 26 | hvals = [20.,25.,30.,35.,40.,45.,50.,55.,60.,65.,70.,75.,80.] # List of heights 27 | NP = len(hvals) 28 | tvals = [-1.]*NP # List of corresponding Time of Flight values 29 | Hstrings = ['H']*NP 30 | Results = [None]*NP # List of Label Widgets 31 | 32 | def calc_g(): 33 | x = [] 34 | y = [] 35 | for k in range(NP): 36 | try: 37 | h = float(Hstrings[k].get()) 38 | if tvals[k] > 0: 39 | t = tvals[k] 40 | else: 41 | continue 42 | x.append(t) 43 | y.append(h) 44 | except: 45 | continue 46 | print (x , y) 47 | if len(x) < 3: 48 | return 49 | y,p=em.fit_qdr(x,y) 50 | g = p[0] * 2 51 | msgwin.config(text = _('Value of "g" by fitting the data points = %5.2f') %g) 52 | 53 | def save(): 54 | x = [] 55 | y = [] 56 | for k in range(NP): 57 | try: 58 | h = float(Hstrings[k].get()) 59 | if tvals[k] > 0: 60 | t = tvals[k] 61 | else: 62 | continue 63 | x.append(t) 64 | y.append(h) 65 | except: 66 | continue 67 | 68 | fname =Fn.get() 69 | f = open(fname,'w') 70 | for k in range(len(x)): 71 | f.write('%5.4f %5.2f\n'%(x[k], y[k])) 72 | f.close() 73 | 74 | def attach(): 75 | p.write_outputs(1) 76 | 77 | def get_tof(index): 78 | try: 79 | h = float(Hstrings[index].get()) 80 | except: 81 | Results[index].config(text = _('Invalid H')) 82 | return 83 | print (index, h) 84 | if (p.read_inputs() & 4) == 0: # ID2 is currently LOW 85 | t = p.clr2rtime(0,2)*1.0e-6 86 | else: 87 | t = p.clr2ftime(0,2)*1.0e-6 88 | if t > 0: 89 | tvals[index] = t 90 | g = 2*h/t**2 91 | print (g) 92 | Results[index].config(text = _('t=%6.4f g=%5.1f') %(t,g)) 93 | else: 94 | Results[index].config(text = _('Timeout Err')) 95 | 96 | 97 | root = Tk() 98 | f1 = Frame(root) 99 | f1.pack(side=TOP, fill = BOTH, expand = 1) 100 | for k in range(NP): 101 | cf = Frame(f1) 102 | cf.pack(side=TOP, fill = BOTH, expand = 1) 103 | b = Button(cf, text = _('Attach Ball at H='), command = attach) 104 | b.pack(side = LEFT, anchor = N) 105 | Hstrings[k] = StringVar() 106 | h =Entry(cf, width=5, bg = 'white', textvariable = Hstrings[k]) 107 | h.pack(side=LEFT) 108 | Hstrings[k].set(str(hvals[k])) 109 | l = Label(cf, text = _('cm')) 110 | l.pack(side = LEFT, anchor = SW) 111 | b = Button(cf, text = _('Measure TOF'), command = lambda i=k : get_tof(i)) 112 | b.pack(side = LEFT, anchor = N) 113 | Results[k] = Label(cf, text = ' '*30) 114 | Results[k].pack(side = LEFT, anchor = SW) 115 | 116 | mf = Frame(root) 117 | mf.pack(side=TOP, fill = BOTH, expand = 1) 118 | msgwin = Label(mf,text=_('Acceleration due to gravity by Time of Flight'), fg = 'blue') 119 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 120 | 121 | cf = Frame(root) 122 | cf.pack(side=TOP, fill = BOTH, expand = 1) 123 | b5 = Button(cf, text = _('FIT'), command = calc_g) 124 | b5.pack(side = LEFT, anchor = N) 125 | b = Button(cf,text =_('Save to'), command=save) 126 | b.pack(side=LEFT, anchor = SW) 127 | Fn = Entry(cf,width = 10, bg = 'white') 128 | Fn.pack(side=LEFT, anchor = SW) 129 | Fn.insert(END,'gravity.dat') 130 | b5 = Button(cf, text = _('QUIT'), command = sys.exit) 131 | b5.pack(side = RIGHT, anchor = N) 132 | 133 | eyeplot.pop_image('pics/g-tof.png', _('Gravity by TOF')) 134 | root.title(_('Gravity by Time of Flight')) 135 | root.mainloop() 136 | -------------------------------------------------------------------------------- /experiments/Lissajous-Figures/Lissajous Figures.md: -------------------------------------------------------------------------------- 1 | Lissajous figures using TWO sine waves 2 | -------------------------------------------------------------------------------- /experiments/Measurements-using-expeyes/Measurements-using-expeyes.py: -------------------------------------------------------------------------------- 1 | ''' 2 | These are procedures for measuring various parameters using ExpEYES Jr 3 | ''' 4 | 5 | 6 | ''' 7 | From croplus.py 8 | ''' 9 | 10 | def measurecap(): 11 | msg(_('Starting Capacitance Measurement..')) 12 | cap = p.measure_cap() 13 | if cap == None: 14 | msg(_('Error: Capacitance too high or short to ground'),'red') 15 | return 16 | g.disp(_('IN1: %6.1f pF')%cap) 17 | if p.socket_cap == 30.0 and p.cap_calib == 1.0: 18 | msg(_('IN1 Not Calibrated.')) 19 | else: 20 | msg(_('IN1: %6.1f pF')%cap) 21 | 22 | 23 | ''' 24 | from eyesj.py 25 | ''' 26 | 27 | def measure_cv(self, ch, ctime, i = 5.5): 28 | ''' 29 | Using the CTMU of PIC, charges a capacitor connected to IN1, IN2 or SEN, 30 | for 'ctime' microseconds and then mesures the voltage across it. 31 | The value of current can be set to .55uA, 5.5 uA, 55uA or 550 uA 32 | @param ch channel number 33 | @param ctime duration in microseconds 34 | @param i value of the current (defaults to 5.5 uA) 35 | ''' 36 | if i > 500: # 550 uA 37 | irange = 0 38 | elif i > 50: #55 uA 39 | irange = 3 40 | elif i > 5: #5.5 uA, default value 41 | irange = 2 42 | else: # 0.55 uA 43 | irange = 1 44 | 45 | if ch not in [3,4]: 46 | self.msg = _('Current to be set only on IN1(3) or IN2(4)') 47 | print (_('Current to be set only on IN1 or IN2')) 48 | return 49 | self.sendByte(MEASURECV) 50 | self.sendByte(chr(ch)) 51 | self.sendByte(chr(irange)) 52 | self.sendInt(ctime) 53 | res = self.fd.read(1) 54 | if res != b'D': 55 | self.msg = warningWithResult(_('MEASURECV ERROR '), res) 56 | print (warningWithResult(_('MEASURECV ERROR '), res)) 57 | return 58 | res = self.fd.read(2) 59 | if sys.version_info.major == 3: 60 | iv = res[0] | (res[1] << 8) 61 | else: 62 | iv = ord(res[0]) | (ord(res[1]) << 8) 63 | v = self.m12[ch] * iv + self.c[ch] 64 | return v 65 | 66 | def measure_cap_raw(self, ctmin = 10): 67 | ''' 68 | Measures the capacitance connected between IN1 and GND. Stray 69 | capacitance should be subtracted from the measured 70 | value. Measurement is done by charging the capacitor with 5.5 uA 71 | for a given time interval. Any error in the value of current 72 | is corrected by calibrating. 73 | ''' 74 | for ctime in range(ctmin, 1000, 10): 75 | v = self.measure_cv(3, ctime, 5.5) # 5.5 uA range is chosen 76 | if v > 2.0: break 77 | if (v > 4) or (v == 0): 78 | self.msg = _('Error measuring capacitance %5.3f') %v 79 | print (_('Error measuring capacitance'), v) 80 | return None 81 | return 5.5 * ctime / v # returns value in pF 82 | 83 | def measure_cap(self, ctmin = 10): 84 | ''' 85 | Measures the capacitance connected between IN1 and GND. 86 | Returns the value after applying corrections. 87 | ''' 88 | cap = self.measure_cap_raw() 89 | if cap != None: 90 | return (cap - self.socket_cap) * self.cap_calib 91 | else: 92 | return None 93 | 94 | -------------------------------------------------------------------------------- /experiments/Mechanics/Spring-Oscillations.md: -------------------------------------------------------------------------------- 1 | Oscillations of a loaded spring using motion sensor SRF-05 2 | A loaded spring executes skmple harmonic motion. By measuring its periodic time, spring constant can be determined. 3 | -------------------------------------------------------------------------------- /experiments/Voltammetry/Voltammetry.md: -------------------------------------------------------------------------------- 1 | ##Voltammetry 2 | 3 | Voltammetry is the study of current as a function of applied potential. These curves I = f(E) are called voltammograms. 4 | 5 | The potential is varied arbitrarily either step by step or continuously, and the actual current value is measured as the dependent variable. 6 | The shape of the curves depends on the speed of potential variation (nature of driving force) and on whether the solution is stirred or quiescent (mass transfer). Most experiments control the potential (volts) of an electrode in contact with the analyte while measuring the resulting current (amperes). 7 | 8 | ExpEYES can be used for these measurements and the cost of the equipment can be reduced considerably. 9 | 10 | 11 | As a part of GSoC 2016 project we have planned to develope a complete module for voltametric measurements. Since ExpEYES doesn't have a bipolar voltage source, we need to convert unipolar voltage to bipolar using external circuit. The GUI will have necessary controls for voltage sweeping. 12 | 13 | There are various types of based on the way voltage sweep is carried out. 14 | 15 | Linear sweep voltammetry 16 | Staircase voltammetry 17 | Squarewave voltammetry 18 | Cyclic voltammetry 19 | 20 | 21 | We are trying to have all these options in this module. 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /experiments/Voltammetry/voltammogram.py: -------------------------------------------------------------------------------- 1 | ''' 2 | ExpEYES program for voltammetric studies. 3 | Voltammetric studies to plot voltammograms are done using costly apparatus in research labs. 4 | ExpEYES can be effectly used for this purpose. 5 | 6 | 7 | ExpEYES program developed as a part of GSoC-2015 project 8 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 9 | Mentor Organization:FOSSASIA 10 | Mentors: Hong Phuc, Mario Behling, Rebentisch 11 | Author: Praveen Patil 12 | License : GNU GPL version 3 13 | 14 | Update : As a part of GSoC-16 project we are working on a complete and affordable open source solution for all types of voltammetric measurements. 15 | 16 | Since ExpEYES does not have a bipolar voltage source, Conversion from Unipolar to Bipolar will be done using external circuit. 17 | 18 | A new tool for Fossasia Science Lab is in the making. It will have inbuilt Bipolar Voltage Source. 19 | 20 | # Modifications needed to change voltage from +1 to -1 volt 21 | ''' 22 | # Connections : PVS to main electrode,Ref. Electrode to GND 23 | import gettext 24 | gettext.bindtextdomain("expeyes") 25 | gettext.textdomain('expeyes') 26 | _ = gettext.gettext 27 | 28 | import time, math, sys 29 | if sys.version_info.major==3: 30 | from tkinter import * 31 | else: 32 | from Tkinter import * 33 | 34 | sys.path=[".."] + sys.path 35 | 36 | import expeyes.eyesj as eyes 37 | import expeyes.eyeplot as eyeplot 38 | import expeyes.eyemath as eyemath 39 | 40 | 41 | 42 | TIMER = 100 43 | WIDTH = 500 # width of drawing canvas 44 | HEIGHT = 350 # height 45 | VPERDIV = 0.25 # Volts per division, vertical scale 46 | delay = 500 # Time interval between samples 47 | NP = 400 # Number of samples 48 | data = [ [], [] ] 49 | history = [] # Data store 50 | trial = 0 # trial number 51 | data = [ [], [] ] # Current & Voltage 52 | 53 | 54 | # to find peaks of the curve... 55 | 56 | def find_peaks(ta,va): # returns the index of the peaks found 57 | vmin = 5.0 58 | vmax = -5.0 59 | p1 = 0 # index of the peaks 60 | p2 = 0 61 | t1 = t2 = 0 62 | size = len(ta) 63 | for i in range(size): 64 | if va[i] < vmin: 65 | vmin = va[i] 66 | p1 = i 67 | if va[i] > vmax: 68 | vmax = va[i] 69 | p2 = i 70 | #print p1,p2,vmin, vmax 71 | if p1 < p2: # return left side peak first 72 | return p1,p2 73 | else: 74 | return p2,p1 75 | 76 | 77 | def base_scan(): 78 | global data, history, trial, NP, delay, noise 79 | t, v = p.capture_hr(1,NP,delay) 80 | g.delete_lines() 81 | g.line(t,v,trial) 82 | running = True 83 | data = [ [], [] ] 84 | p1,p2 = find_peaks(t,v) 85 | noise = abs(v[p1]) 86 | msgwin.config(text = _('Voltage Scan on Coil Done. Noise Voltage = %5.3f V')%noise) 87 | root.after(TIMER, update) 88 | 89 | def update(): 90 | global data, history, trial, NP, delay, noise 91 | p.set_voltage(1.0) # set voltage on PVS 92 | t, v= p.capture_hr(1,NP,delay) # Scan for 5 times more 93 | p1,p2 = find_peaks(t,v) 94 | #print v[p1], v[p2] 95 | if abs(v[p1] - noise) > 0.5 and p1 < .9*NP: # Signal at least 0.5 volts above noise 96 | index = p1-50 97 | tbeg = t[index] 98 | ''' 99 | tn = [] 100 | vn = [] 101 | while index < p1 + 150: 102 | #print index 103 | tn.append(t[index]-tbeg) 104 | vn.append(v[index]) 105 | index += 1 106 | ''' 107 | g.delete_lines() 108 | g.line(t,v,trial) 109 | data = [t,v] 110 | s = _('Peak voltages %5.2f and %5.3f separated by %5.3f msec') %(v[p1], v[p2], t[p2]-t[p1]) 111 | msgwin.config(text = s) 112 | #print len(tn), len(vn), v[p1], v[p2] 113 | history.append(data) 114 | trial += 1 115 | return 116 | root.after(TIMER, update) 117 | 118 | def clear(): 119 | global history, trial 120 | g.delete_lines() 121 | history = [] 122 | trial = 0 123 | 124 | def save(): 125 | global history 126 | s = fn.get() 127 | if s == '': 128 | return 129 | p.save(history, s) 130 | msgwin.config(text = _('Data saved to file ')+s) 131 | 132 | def viewall(): # Send the data to Xmgrace 133 | global history 134 | g.delete_lines() 135 | i = 0 136 | for t,v in history: 137 | g.line(t,v,i) 138 | i += 1 139 | 140 | p = eyes.open() 141 | root = Tk() 142 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 143 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT) # make plot objects using draw.disp 144 | g.setWorld(0,-5*VPERDIV, NP * delay * 0.001, 5*VPERDIV,_('mS'),_('V')) 145 | 146 | cf = Frame(root, width = WIDTH, height = 10) 147 | cf.pack(side=TOP, fill = BOTH, expand = 1) 148 | b = Button(cf,text =_('Start Scanning'), command= base_scan) 149 | b.pack(side=LEFT, anchor = SW) 150 | 151 | b = Button(cf,text =_('Save to'), command=save) 152 | b.pack(side=LEFT, anchor = SW) 153 | fn = Entry(cf,width = 10, bg = 'white') 154 | fn.pack(side=LEFT, anchor = SW) 155 | fn.insert(END,'ind.dat') 156 | b = Button(cf,text =_('QUIT'), command=sys.exit) 157 | b.pack(side=RIGHT, anchor = SW) 158 | b = Button(cf,text =_('VIEW'), command=viewall) 159 | b.pack(side=RIGHT, anchor = SW) 160 | b4 = Button(cf, text = _('CLEAR'), command = clear) 161 | b4.pack(side = RIGHT, anchor = N) 162 | 163 | mf = Frame(root) # Message Frame below command frame. 164 | mf.pack(side=TOP, anchor = SW) 165 | msgwin = Label(mf,text = _('Messages'), fg = 'blue') 166 | msgwin.pack(side=LEFT, anchor = SW) 167 | 168 | 169 | root.title(_('EYESJUN: Voltamogram')) 170 | root.mainloop() 171 | -------------------------------------------------------------------------------- /experiments/Weather-Station/Weather-Data-Logger.py: -------------------------------------------------------------------------------- 1 | ''' 2 | ExpEYES-Weather Station GUI 3 | 4 | ExpEYES program developed as a part of GSoC-2015 project 5 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 6 | 7 | Mentor Organization:FOSSASIA 8 | Mentors: Hong Phuc, Mario Behling, Rebentisch 9 | Author: Praveen Patil 10 | License : GNU GPL version 3 11 | 12 | This programme is for logging weather data like temperature,barometric pressure, Relative humidity and wind speed. 13 | ''' 14 | 15 | 16 | import gettext 17 | gettext.bindtextdomain("expeyes") 18 | gettext.textdomain('expeyes') 19 | _ = gettext.gettext 20 | 21 | 22 | import time, math, sys 23 | if sys.version_info.major==3: 24 | from tkinter import * 25 | else: 26 | from Tkinter import * 27 | 28 | sys.path=[".."] + sys.path 29 | 30 | import expeyes.eyesj as eyes 31 | import expeyes.eyeplot as eyeplot 32 | import expeyes.eyemath as eyemath 33 | 34 | WIDTH = 800 # width of drawing canvas 35 | HEIGHT = 600 # height 36 | 37 | # Connections 38 | # Humidity sensor HS1101 to IN1 and GND 39 | # Temperature sensor LM-35 to IN2, OD1 and GND 40 | # Barrometric Pressure Sensor to A2 41 | # Anemometer to A1 42 | # Wind Direction Device to SEN 43 | 44 | class WS: 45 | tv = [ [], [], [], [], [], [] ] # Six Lists for Readings time, v , v1, v2, v3 and v4 46 | TIMER = 500 # Time interval between reads 47 | MINY = 0 # Voltage range 48 | MAXY = 100 49 | running = False 50 | MAXTIME = 10 51 | 52 | 53 | def v2t(self, v): # Convert Voltage to Temperature for LM35 54 | 55 | t = v * 100 56 | return t 57 | 58 | def start(self): 59 | self.running = True 60 | self.index = 0 61 | p.set_state(10,1) 62 | self.tv = [ [], [], [], [], [], [] ] 63 | try: 64 | self.MAXTIME = int(DURATION.get()) 65 | self.MINY = int(TMIN.get()) 66 | self.MAXY = int(TMAX.get()) 67 | 68 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time in second'),_('Data')) 69 | self.TIMER = int(TGAP.get()) 70 | Total.config(state=DISABLED) 71 | Dur.config(state=DISABLED) 72 | self.msg(_('Starting the Measurements')) 73 | root.after(self.TIMER, self.update) 74 | except: 75 | self.msg(_('Failed to Start')) 76 | pass 77 | 78 | def stop(self): 79 | self.running = False 80 | Total.config(state=NORMAL) 81 | Dur.config(state=NORMAL) 82 | self.msg(_('User Stopped the measurements')) 83 | 84 | 85 | def update(self): 86 | if self.running == False: 87 | return 88 | t,v = p.get_voltage_time(4) # Read IN2 for temperature sensor 89 | if len(self.tv[0]) == 0: 90 | self.start_time = t 91 | elapsed = 0 92 | else: 93 | elapsed = t - self.start_time # To be done : make changes to have system time 94 | self.tv[0].append(elapsed) 95 | 96 | temp = self.v2t(v) 97 | self.tv[1].append(temp) 98 | 99 | cap = p.measure_cap() 100 | 101 | if cap< 180: 102 | RH= (cap -163)/0.3 103 | elif 180= 2: 125 | g.delete_lines() 126 | 127 | g.line(self.tv[0], self.tv[1],1) # red line - temperature in celsius scale 128 | g.line(self.tv[0], self.tv[2],2) # blue line - Relative Humidity in % 129 | g.line(self.tv[0], self.tv[3],0) # black line - A1 130 | g.line(self.tv[0], self.tv[4],5) # green line -A2 131 | g.line(self.tv[0], self.tv[5],6) #yellow line - SEN 132 | 133 | if elapsed > self.MAXTIME: 134 | self.running = False 135 | Total.config(state=NORMAL) 136 | Dur.config(state=NORMAL) 137 | self.msg(_('Completed the Measurements')) 138 | return 139 | root.after(self.TIMER, self.update) 140 | 141 | def save(self): 142 | try: 143 | fn = filename.get() 144 | except: 145 | fn = 'weather-station.dat' 146 | p.save([self.tv],fn) 147 | self.msg(_('Data saved to %s')%fn) 148 | 149 | def clear(self): 150 | if self.running == True: 151 | return 152 | self.tv = [ [], [], [], [], [], [] ] 153 | g.delete_lines() 154 | self.msg(_('Cleared Data and Trace')) 155 | 156 | def msg(self,s, col = 'blue'): 157 | msgwin.config(text=s, fg=col) 158 | 159 | def quit(self): 160 | #p.set_state(10,0) 161 | sys.exit() 162 | 163 | p = eyes.open() 164 | p.disable_actions() 165 | 166 | root = Tk() 167 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 168 | 169 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 170 | pt = WS() 171 | 172 | cf = Frame(root, width = WIDTH, height = 10) 173 | cf.pack(side=TOP, fill = BOTH, expand = 1) 174 | 175 | b3 = Label(cf, text = _('Read Every')) 176 | b3.pack(side = LEFT, anchor = SW) 177 | TGAP = StringVar() 178 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 179 | TGAP.set('1000') 180 | Dur.pack(side = LEFT, anchor = SW) 181 | b3 = Label(cf, text = _('mS,')) 182 | b3.pack(side = LEFT, anchor = SW) 183 | b3 = Label(cf, text = _('for total')) 184 | b3.pack(side = LEFT, anchor = SW) 185 | DURATION = StringVar() 186 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 187 | DURATION.set('100') 188 | Total.pack(side = LEFT, anchor = SW) 189 | b3 = Label(cf, text = _('Seconds.')) 190 | b3.pack(side = LEFT, anchor = SW) 191 | 192 | b3 = Label(cf, text = _('Range')) 193 | b3.pack(side = LEFT, anchor = SW) 194 | TMIN = StringVar() 195 | TMIN.set('0') 196 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 197 | Tmin.pack(side = LEFT, anchor = SW) 198 | b3 = Label(cf, text = _('to,')) 199 | b3.pack(side = LEFT, anchor = SW) 200 | TMAX = StringVar() 201 | TMAX.set('100') 202 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 203 | Tmax.pack(side = LEFT, anchor = SW) 204 | b3 = Label(cf, text = _('C. ')) 205 | 206 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 207 | b3.pack(side = LEFT, anchor = SW) 208 | b3.pack(side = LEFT, anchor = SW) 209 | filename = StringVar() 210 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 211 | filename.set('temperature.dat') 212 | e1.pack(side = LEFT, anchor = SW) 213 | 214 | cf = Frame(root, width = WIDTH, height = 10) 215 | cf.pack(side=TOP, fill = BOTH, expand = 1) 216 | 217 | cf = Frame(root, width = WIDTH, height = 10) 218 | cf.pack(side=TOP, fill = BOTH, expand = 1) 219 | e1.pack(side = LEFT) 220 | 221 | b3 = Label(cf, text = _(' RED Line - Temperature in Celsius'), fg = 'red') 222 | b3.pack(side = LEFT, anchor = SW) 223 | b3 = Label(cf, text = _(' BLUE Line - Relative Humidity in %'), fg = 'blue') # Add info for other data lines 224 | b3.pack(side = LEFT, anchor = SW) 225 | 226 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 227 | b5.pack(side = RIGHT, anchor = N) 228 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 229 | b4.pack(side = RIGHT, anchor = N) 230 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 231 | b1.pack(side = RIGHT, anchor = N) 232 | b1 = Button(cf, text = _('START'), command = pt.start) 233 | b1.pack(side = RIGHT, anchor = N) 234 | 235 | mf = Frame(root, width = WIDTH, height = 10) 236 | mf.pack(side=TOP) 237 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 238 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 239 | 240 | 241 | eyeplot.pop_image('pics/image-name.png', _('---')) # save the image in the same directory as of the program 242 | root.title(_('ExpEYES- Weather Station Data Logger')) 243 | root.mainloop() 244 | -------------------------------------------------------------------------------- /experiments/Weather-Station/weather-station-data.dat: -------------------------------------------------------------------------------- 1 | 0.00 24.0 13.1 91 2 | 30.00 24.0 13.6 92 3 | 60.00 23.5 12.0 93 4 | 90.00 23.0 10.0 93 5 | 120.00 23.0 11.0 94 6 | 150.00 23.0 11.3 94 7 | 180.00 22.5 10.7 93 8 | 210.00 22.0 11.6 94 9 | 240.00 21.0 9.5 93 10 | 270.00 21.0 11.6 93 11 | 300.00 21.0 12.4 94 12 | 330.00 21.0 11.4 93 13 | 360.00 21.0 11.7 94 14 | -------------------------------------------------------------------------------- /experiments/Weather-Station/weather-station.md: -------------------------------------------------------------------------------- 1 | Programs for interfacing sensors with ExpEYES to collect weather data. 2 | Sensor measurements for the weather station: 3 | 4 | 1. Wind speed 5 | 2. Wind direction 6 | 3. Ambient temperature 7 | 4. Soil temperature 8 | 5. Barometric pressure 9 | 6. Relative humidity 10 | 7. Real Time Clock (for data logging purposes) 11 | 12 | -------------------------------------------------------------------------------- /experiments/control-PVS/control-PVS.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Program to control PVS programable voltage source in ExpEYES 3 | Useful in voltametry and other applications where voltage needs to be changed 4 | ''' 5 | 6 | 7 | 8 | 9 | import sys 10 | 11 | if sys.version_info.major==3: 12 | from tkinter import * 13 | else: 14 | from Tkinter import * 15 | 16 | sys.path=[".."] + sys.path 17 | import expeyes.eyesj, expeyes.eyeplot as eyeplot 18 | 19 | p=expeyes.eyesj.open() 20 | 21 | import gettext 22 | gettext.bindtextdomain("expeyes") 23 | gettext.textdomain('expeyes') 24 | _ = gettext.gettext 25 | 26 | def set_pvs(w): 27 | state = int(Pvs.get()) 28 | iv = int(Pvs.get()) 29 | p.write_dac(iv) 30 | v = p.get_voltage(12) 31 | Res.config(text=_('PVS = %5.3f volts')%v) 32 | w = Tk() 33 | Label(text=_('To change PVS drag the slider. For fine adjustment, click on its left or right')).pack(side=TOP) 34 | Pvs = Scale(w,command = set_pvs, orient=HORIZONTAL, length=500, showvalue=False, from_ = 0, to=4095, resolution=1) 35 | Pvs.pack(side=TOP) 36 | Res = Label(text = '', fg = 'blue') 37 | Res.pack(side=TOP) 38 | Button(text=_('QUIT'), command=sys.exit).pack(side=TOP) 39 | w.title(_('EYES Junior: Adjust PVS')) 40 | w.mainloop() 41 | 42 | -------------------------------------------------------------------------------- /experiments/velocityofsoundUsingPiezo/velocityofsoundUsingPiezo.py: -------------------------------------------------------------------------------- 1 | ''' 2 | ExpEYES Program 3 | GSoC- 2016 4 | Author: Praveen Patil 5 | License : GPL 6 | ''' 7 | 8 | from __future__ import print_function 9 | 10 | import gettext 11 | gettext.bindtextdomain("expeyes") 12 | gettext.textdomain('expeyes') 13 | _ = gettext.gettext 14 | 15 | import sys 16 | if sys.version_info.major==3: 17 | from tkinter import * 18 | else: 19 | from Tkinter import * 20 | import expeyes.eyes as eyes, expeyes.eyeplot as eyeplot 21 | 22 | 23 | def get_tof(): 24 | t = p.pulse2rtime(1,2) 25 | if t > 0: 26 | res.config(text = _('%8.6f sec')%(t*1.0e-6)) 27 | else: 28 | res.config(text = _('Error..')) 29 | 30 | p = eyes.open() 31 | p.disable_actions() 32 | 33 | root = Tk() 34 | cf = Frame(root) 35 | cf.pack(side=TOP, fill = BOTH, expand = 1) 36 | 37 | Label(cf,text = _('Connect Transmitter from OD1 to Ground')).pack() 38 | Label(cf,text = _('Connect Receiver from T15 to Ground')).pack() 39 | Label(cf,text = _('Keep them facing each other, at a known distance')).pack() 40 | 41 | b1 = Button(cf, text = _('Measure Time of Travel'), command = get_tof) 42 | b1.pack(side = TOP, anchor = N) 43 | res = Label(cf, text = '') 44 | res.pack(side = TOP, anchor = N) 45 | b5 = Button(cf, text = _('QUIT'), command = sys.exit) 46 | b5.pack(side = TOP, anchor = N) 47 | 48 | eyeplot.pop_image('pics/xxxxx.png', _('Velocity of Sound, 40kHz')) 49 | root.title(_('Velocity of Sound')) 50 | root.mainloop() 51 | 52 | -------------------------------------------------------------------------------- /lang/Makefile: -------------------------------------------------------------------------------- 1 | DESTDIR = 2 | SOURCES = $(shell find .. -name "*.py") 3 | POFILES = $(shell ls *.po) 4 | MOFILES = $(patsubst %.po, %.mo, $(POFILES)) 5 | LANG = $(patsubst %.po, %, $(POFILES)) 6 | 7 | all: $(MOFILES) 8 | 9 | %.mo: %.po 10 | msgfmt --output-file=$@ $< 11 | 12 | $(POFILES): messages.pot 13 | for f in $(POFILES); do \ 14 | msgmerge --update --previous $$f messages.pot; \ 15 | done 16 | 17 | messages.pot: $(SOURCES) 18 | if [ -f $@ ]; then \ 19 | xgettext --output=$@ --language=python --join-existing --keyword=_ --add-location $(SOURCES); \ 20 | else \ 21 | xgettext --output=$@ --language=python --keyword=_ --add-location $(SOURCES); \ 22 | fi 23 | 24 | clean: 25 | rm -f messages.pot *.mo *~ 26 | 27 | install: all 28 | for l in $(LANG); do \ 29 | install -d $(DESTDIR)/usr/share/locale/$$l/LC_MESSAGES; \ 30 | install -m 644 $$l.mo $(DESTDIR)/usr/share/locale/$$l/LC_MESSAGES/expeyes.mo; \ 31 | done 32 | 33 | .PHONY: all clean install 34 | -------------------------------------------------------------------------------- /sensors/ATTINY85-MCU/ATTINY85.md: -------------------------------------------------------------------------------- 1 | #ATTINY-85 2 | The high-performance, low-power Atmel 8-bit AVR RISC-based microcontroller combines 8KB ISP flash memory, 512B EEPROM, 512-Byte SRAM, 6 general purpose I/O lines, 32 general purpose working registers, one 8-bit timer/counter with compare modes, one 8-bit high speed timer/counter, USI, internal and external Interrupts, 4-channel 10-bit A/D converter, programmable watchdog timer with internal oscillator, three software selectable power saving modes, and debugWIRE for on-chip debugging. 3 | The device achieves a throughput of 20 MIPS at 20 MHz and operates between 2.7-5.5 volts. 4 | 5 | By executing powerful instructions in a single clock cycle, the device achieves throughputs approaching 1 MIPS per MHz, balancing power consumption and processing speed. 6 | 7 | 8 | -------------------------------------------------------------------------------- /sensors/ATTINY85-MCU/Lissajous.py: -------------------------------------------------------------------------------- 1 | ''' 2 | expEYES lissajous program 3 | Developed as a part of GSoC Project 4 | License : GNU GPL version 3 5 | 6 | connect AATINY85 module to IN1 and IN2 7 | black wire to GND 8 | Green is SQR input (pin 2) 9 | Red is output (pin 3) 10 | Module can be powered using USB or external USB adapter. 11 | the second module can be powered fron first from (P2VUSB pin) 12 | pin P1 can be touched to groung to RESET 13 | ''' 14 | 15 | from __future__ import print_function 16 | 17 | import gettext 18 | gettext.bindtextdomain("expeyes") 19 | gettext.textdomain('expeyes') 20 | _ = gettext.gettext 21 | import time, math, sys 22 | if sys.version_info.major==3: 23 | from tkinter import * #support for python 3 24 | else: 25 | from Tkinter import * 26 | sys.path=[".."] + sys.path 27 | import expeyes.eyesj as eyes 28 | import expeyes.eyeplot as eyeplot 29 | import expeyes.eyemath as eyemath 30 | 31 | 32 | #from Tkinter import* 33 | #import expeyes.eyesj as eyes, expeyes.eyeplot as eyeplot, expeyes.eyemath as eyemath, time, math 34 | 35 | TIMER = 100 36 | WIDTH = 800 # width of drawing canvas 37 | HEIGHT = 400 # height 38 | delay = 50 # Time interval between samples 39 | NP = 450 # Number of samples 40 | data = [] # Of the form, [ [x1,y1], [x2,y2],....] where x and y are vectors 41 | outmask = 1 42 | looping = False 43 | 44 | 45 | def start(): 46 | global data,looping, NP, delay 47 | p.disable_actions() 48 | msec = int(Nsam.get()) 49 | if 1 <= msec <= 200: # total time 50 | delay = msec * 1000/ NP 51 | else: 52 | delay = 50 * 1000/NP 53 | print (NP, delay, NP*delay) 54 | g.setWorld(-5,-5, 5, 5,_('Volts'),_('Volts')) 55 | 56 | f = float(Freq0.get()) 57 | fr = p.set_sqr1(f*32) 58 | f = float(Freq.get()) 59 | fr = p.set_sqr2(f*32) 60 | data = [] 61 | t,v,tt,vv = p.capture2_hr(3,4,NP,delay) 62 | g.delete_lines() 63 | g.line(v,vv) 64 | data.append([v,vv]) 65 | 66 | def save(): 67 | global data 68 | s = fn.get() 69 | if s == '': 70 | return 71 | p.save(data, s) 72 | msgwin.config(text = _('Data saved to file ')+s) 73 | 74 | def quit(): 75 | sys.exit() 76 | 77 | p = eyes.open() 78 | p.set_sqr1(0) 79 | 80 | root = Tk() 81 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 82 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT) # make plot objects using draw.disp 83 | g.setWorld(0,-5, NP * delay * 0.001, 5,_('mS'),_('V')) 84 | 85 | if p == None: 86 | g.text(0, 0,_('EYES Hardware Not Found. Check Connections and restart the program'),1) 87 | root.mainloop() 88 | sys.exit() 89 | 90 | cf = Frame(root, width = WIDTH, height = 10) 91 | cf.pack(side=TOP, fill = BOTH, expand = 1) 92 | 93 | l = Label(cf,text='Sampling Time =') 94 | l.pack(side=LEFT, anchor=SW) 95 | Nsam = Entry(cf,width = 4, bg = 'white') 96 | Nsam.pack(side=LEFT, anchor = SW) 97 | Nsam.insert(END,'50') 98 | l = Label(cf,text='mS') 99 | l.pack(side=LEFT, anchor=SW) 100 | l = Label(cf,text='SINE1=') 101 | l.pack(side=LEFT, anchor=SW) 102 | Freq0 = Entry(cf,width = 10, bg = 'white') 103 | Freq0.pack(side=LEFT, anchor = SW) 104 | Freq0.insert(END,'100') 105 | 106 | 107 | l = Label(cf,text='SINE2=') 108 | l.pack(side=LEFT, anchor=SW) 109 | Freq = Entry(cf,width = 10, bg = 'white') 110 | Freq.pack(side=LEFT, anchor = SW) 111 | Freq.insert(END,'200') 112 | 113 | Start = Button(cf,text =_('DRAW'), command = start, fg = 'blue') 114 | Start.pack(side=LEFT, anchor = SW) 115 | 116 | 117 | b = Button(cf,text =_('Save to'), command=save) 118 | b.pack(side=LEFT, anchor = SW) 119 | fn = Entry(cf,width = 10, bg = 'white') 120 | fn.pack(side=LEFT, anchor = SW) 121 | fn.insert(END,'lissajous.dat') 122 | b = Button(cf,text =_('QUIT'), command=quit) 123 | b.pack(side=RIGHT, anchor = SW) 124 | 125 | 126 | mf = Frame(root) # Message Frame below command frame. 127 | mf.pack(side=TOP, anchor = SW) 128 | msgwin = Label(mf,text = _('Messages'), fg = 'blue') 129 | msgwin.pack(side=LEFT, anchor = SW) 130 | 131 | eyeplot.pop_image('pics/lissa.png', _('Lissajous Figures')) 132 | root.title(_('EYES: Lissajous Figures')) 133 | root.mainloop() 134 | -------------------------------------------------------------------------------- /sensors/AccelerometerADXL335/ADXL335.md: -------------------------------------------------------------------------------- 1 | ## Analog acceleration sensor module using ADXL335 - GY-61 2 | GY-61 is a small, thin, low power, complete three-axis accelerometer voltage output through the signal conditioning at a minimum of full scale ± 3 g measurement range acceleration. It can measure the tilt-sensing applications in the static acceleration of gravity, and movement, shock or vibration due to dynamic acceleration. 3 | 4 | 5 | Data Sheet: https://www.sparkfun.com/datasheets/Components/SMD/adxl335.pdf 6 | 7 | 8 | #### Accelerometer 9 | 10 | Accelerometers measure acceleration. That is acceleration due to movement and also acceleration due to gravity. Accelerometers are often used to calculate a tilt angle. They can only do this reliably when they are static and not moving. To get an accurate angle of tilt they are often combined with one or more gyro's and the combination of data is used to calculate the angle. 11 | 12 | Digital accelerometers will give you information using a serial protocol like I2C , SPI or USART, while analog accelerometers will output a voltage level within a predefined range that you have to convert to a digital value using an ADC (analog to digital converter) module. 13 | 14 | ####What does an accelerometer measure? 15 | 16 | Accelerometers measure acceleration. For a static object that is the acceleration due to gravity (1g). Note also, that the output from accelerometers is not linear but is a sinewave, so you cannot take the direct output as a proportional representation of an angle of tilt based on gravity. 17 | 18 | Normally an accelerometer's x and y output voltages will be half the supply voltage when measuring zero g (i.e. the device is perpendicular to gravity - horizontal). Tilt it one way and the voltage will increase, tilt it the other way and it will decrease. With a Triple axis accelerometer the z axis will be measuring 1g with the device horizontal. The output of an accelerometer is a sinewave of the acceleration measured. Accelerometers are more sensitive to small changes in tilt when they are perpendicular to gravity. I.e. when horizontal, small changes in tilt give useful readings. Past about 45 degrees of tilt they become increasingly less sensitive. For this reason it is common to use more than one axis value when determining the angle of tilt as will be seen below. 19 | 20 | ####Measuring Tilt Angle using One Axis 21 | 22 | If you want to measure tilt in both x and y axis with a 2-axis accelerometer then you can simply use sin-1(a) where a is the output from one axis of the accelerometer. 23 | 24 | Remember that beyond +45 and -45 degrees the accuracy will diminish 25 | 26 | 27 | 28 | 29 | ####Measuring Tilt Angle using Three Axis 30 | 31 | For accurate measurements of tilt in the x and y planes we therefore need a 3 axis accelerometer. We could use the formula above to calculate the angles using x and z for the x axis and using y and z for the y axis. However we can improve things further by using all three outputs to calculate each angle. 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /sensors/AccelerometerADXL335/Tilt-angle-GUI.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI Program to plot acceleration data using ADXL335 sensor in real-time 3 | 4 | 5 | ExpEYES program developed as a part of GSoC-2015 project 6 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 7 | Mentor Organization:FOSSASIA 8 | Mentors: Hong Phuc, Mario Behling, Rebentisch 9 | Author: Praveen Patil 10 | License : GNU GPL version 3 11 | 12 | Calibration: 13 | For calculating acceleration in terms of g 14 | Ref: https://www.sparkfun.com/datasheets/Components/SMD/adxl335.pdf 15 | For 0g v = 1.61 volt 16 | -1g v = 1.31 volt 17 | +1g v = 1.91 volt 18 | Sensitivity 0.3v/g 19 | 20 | For tilt angle calculation: 21 | atan2(y, x)-------- Returns atan(y / x), in radians. The result is between -pi and pi. The vector in the plane from the origin to point (x, y) makes this angle with the positive X axis. The point of atan2() is that the signs of both inputs are known to it, so it can compute the correct quadrant for the angle. For example, atan(1) and atan2(1, 1) are both pi/4, but atan2(-1, -1) is -3*pi/4. 22 | 23 | The rotation(for x axis) is calculated using atan2 function. It calculates angle from length of y, z vectors. 57.2957795 is conversation of radian to degree. +180 is for offset. 24 | 25 | 26 | ''' 27 | 28 | from __future__ import print_function 29 | 30 | import gettext #Internationalization 31 | gettext.bindtextdomain("expeyes") 32 | gettext.textdomain('expeyes') 33 | _ = gettext.gettext 34 | 35 | 36 | import time, math, sys 37 | if sys.version_info.major==3: # Python 3 compatibility 38 | from tkinter import * 39 | else: 40 | from Tkinter import * 41 | 42 | sys.path=[".."] + sys.path 43 | 44 | import expeyes.eyesj as eyes 45 | import expeyes.eyeplot as eyeplot 46 | import expeyes.eyemath as eyemath 47 | 48 | from math import* # for using function atan2 49 | 50 | 51 | WIDTH = 600 # width of drawing canvas 52 | HEIGHT = 400 # height 53 | 54 | class tilt: 55 | tv = [ [], [], [], [] ] # Three Lists for Readings time, v1, v2, v3 56 | TIMER = 5 # Time interval between reads 57 | MINY = -360 # Voltage range 58 | MAXY = 360 59 | running = False 60 | MAXTIME = 10 61 | VZERO = 1.6 # voltage at zero g 62 | SEN = 0.3 # sensitivity 0.3v/g 63 | 64 | 65 | def xmgrace(self): 66 | if self.running == True: 67 | return 68 | p.grace([self.tv]) 69 | 70 | def start(self): 71 | 72 | print (p.set_voltage(3.6)) # set voltage at PVS 3.6v is operating voltage for ADXL335 73 | self.running = True 74 | self.index = 0 75 | self.tv = [ [], [], [], [] ] 76 | try: 77 | 78 | self.MAXTIME = int(DURATION.get()) 79 | self.MINY = int(TMIN.get()) 80 | self.MAXY = int(TMAX.get()) 81 | 82 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('Acceleration g')) 83 | self.TIMER = int(TGAP.get()) 84 | Total.config(state=DISABLED) 85 | Dur.config(state=DISABLED) 86 | self.msg(_('Starting the Measurements')) 87 | root.after(self.TIMER, self.update) 88 | except: 89 | self.msg(_('Failed to Start')) 90 | pass 91 | 92 | def stop(self): 93 | self.running = False 94 | Dur.config(state=NORMAL) 95 | self.msg(_('User Stopped the measurements')) 96 | 97 | def update(self): 98 | if self.running == False: 99 | return 100 | t,v = p.get_voltage_time(1) # Read A1 101 | v2 = p.get_voltage(2) # Read A2 102 | v3 = p.get_voltage(3) # Read IN1 103 | 104 | Xaccl = (v-1.6) / 0.3 105 | Yaccl = (v2-1.6) / 0.3 106 | Zaccl = (v3-1.6) / 0.3 107 | 108 | 109 | angle_x =atan2(-Yaccl,-Zaccl)*57.2957795+180; 110 | 111 | angle_y =atan2(-Zaccl,-Xaccl)*57.2957795+180; 112 | 113 | angle_z =atan2(-Xaccl,-Yaccl)*57.2957795+180; 114 | 115 | #changes required to measure angle between +180 to -180 degrees 116 | 117 | #print ("Tilt angle X-axis = ", angle_x, "degree") 118 | #print ("Tilt angle Y-axis = ", angle_y, "degree") 119 | #print ("Tilt Calibration:) 120 | 121 | 122 | if len(self.tv[0]) == 0: 123 | self.start_time = t 124 | elapsed = 0 125 | else: 126 | elapsed = t - self.start_time 127 | 128 | self.tv[0].append(elapsed) 129 | self.tv[1].append(angle_x) 130 | self.tv[2].append(angle_y) 131 | self.tv[3].append(angle_z) 132 | 133 | if len(self.tv[0]) >= 2: 134 | g.delete_lines() 135 | g.line(self.tv[0], self.tv[1]) # Black line for x-axis 136 | g.line(self.tv[0], self.tv[2],1) # Red line for y-axis 137 | g.line(self.tv[0], self.tv[3],2) # Blue line for z-axis 138 | if elapsed > self.MAXTIME: 139 | self.running = False 140 | Total.config(state=NORMAL) 141 | Dur.config(state=NORMAL) 142 | self.msg(_('Completed the Measurements')) 143 | return 144 | root.after(self.TIMER, self.update) 145 | 146 | 147 | def save(self): 148 | try: 149 | fn = filename.get() 150 | except: 151 | fn = 'tiltangle.dat' 152 | p.save([self.tv],fn) 153 | self.msg(_('Data saved to %s')%fn) 154 | 155 | def clear(self): 156 | if self.running == True: 157 | return 158 | self.tv = [ [], [], [], [] ] 159 | g.delete_lines() 160 | self.msg(_('Cleared Data and Trace')) 161 | 162 | def msg(self,s, col = 'blue'): 163 | msgwin.config(text=s, fg=col) 164 | def quit(self): 165 | sys.exit() 166 | 167 | p = eyes.open() 168 | p.disable_actions() 169 | root = Tk() 170 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 171 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) # make plot objects using draw.disp 172 | pen = tilt() 173 | 174 | cf = Frame(root, width = WIDTH, height = 10) 175 | cf.pack(side=TOP, fill = BOTH, expand = 1) 176 | 177 | 178 | b3 = Label(cf, text = _('Read Every')) 179 | b3.pack(side = LEFT, anchor = SW) 180 | TGAP = StringVar() 181 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 182 | TGAP.set('5') 183 | Dur.pack(side = LEFT, anchor = SW) 184 | b3 = Label(cf, text = _('mS,')) 185 | b3.pack(side = LEFT, anchor = SW) 186 | b3 = Label(cf, text = _('for total')) 187 | b3.pack(side = LEFT, anchor = SW) 188 | DURATION = StringVar() 189 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 190 | DURATION.set('10') 191 | Total.pack(side = LEFT, anchor = SW) 192 | b3 = Label(cf, text = _('Seconds.')) 193 | b3.pack(side = LEFT, anchor = SW) 194 | 195 | b3 = Label(cf, text = _('Range')) 196 | b3.pack(side = LEFT, anchor = SW) 197 | TMIN = StringVar() 198 | TMIN.set('-5') 199 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 200 | Tmin.pack(side = LEFT, anchor = SW) 201 | b3 = Label(cf, text = _('to,')) 202 | b3.pack(side = LEFT, anchor = SW) 203 | TMAX = StringVar() 204 | TMAX.set('5') 205 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 206 | Tmax.pack(side = LEFT, anchor = SW) 207 | b3 = Label(cf, text = _('C. ')) 208 | 209 | b3 = Button(cf, text = _('SAVE to'), command = pen.save) 210 | b3.pack(side = LEFT, anchor = SW) 211 | b3.pack(side = LEFT, anchor = SW) 212 | filename = StringVar() 213 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 214 | filename.set('tiltangle.dat') 215 | e1.pack(side = LEFT, anchor = SW) 216 | 217 | cf = Frame(root, width = WIDTH, height = 10) 218 | cf.pack(side=TOP, fill = BOTH, expand = 1) 219 | 220 | b1 = Button(cf, text = _('Xmgrace'), command = pen.xmgrace) 221 | b1.pack(side = LEFT, anchor = SW) 222 | 223 | b3 = Label(cf, text = _(' Black Line : X-axis'), fg = 'black') 224 | b3.pack(side = LEFT, anchor = SW) 225 | b3 = Label(cf, text = _(' RED Line : Y-axis'), fg = 'red') 226 | b3.pack(side = LEFT, anchor = SW) 227 | b3 = Label(cf, text = _(' BLUE Line - Z-axis'), fg = 'blue') 228 | b3.pack(side = LEFT, anchor = SW) 229 | 230 | cf = Frame(root, width = WIDTH, height = 10) 231 | cf.pack(side=TOP, fill = BOTH, expand = 1) 232 | e1.pack(side = LEFT) 233 | 234 | 235 | b5 = Button(cf, text = _('QUIT'), command = pen.quit) 236 | b5.pack(side = RIGHT, anchor = N) 237 | b4 = Button(cf, text = _('CLEAR'), command = pen.clear) 238 | b4.pack(side = RIGHT, anchor = N) 239 | b1 = Button(cf, text = _('STOP'), command = pen.stop) 240 | b1.pack(side = RIGHT, anchor = N) 241 | b1 = Button(cf, text = _('START'), command = pen.start) 242 | b1.pack(side = RIGHT, anchor = N) 243 | 244 | 245 | mf = Frame(root, width = WIDTH, height = 10) 246 | mf.pack(side=TOP) 247 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 248 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 249 | 250 | root.title(_('Accelerometer ADXL 335 Tilt angle Measurement ')) 251 | root.mainloop() 252 | -------------------------------------------------------------------------------- /sensors/AccelerometerADXL335/Tilt-angle-measurement.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI Program to calculate tilt angle using ADXL335 sensor 3 | 4 | 5 | ExpEYES program developed as a part of GSoC-2015 project 6 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 7 | Mentor Organization:FOSSASIA 8 | Mentors: Hong Phuc, Mario Behling, Rebentisch 9 | Author: Praveen Patil 10 | License : GNU GPL version 3 11 | 12 | Calibration: 13 | For calculating acceleration in terms of g 14 | Ref: https://www.sparkfun.com/datasheets/Components/SMD/adxl335.pdf 15 | For 0g v = 1.61 volt 16 | -1g v = 1.31 volt 17 | +1g v = 1.91 volt 18 | Sensitivity 0.3v/g 19 | 20 | For tilt angle calculation: 21 | atan2(y, x)-------- Returns atan(y / x), in radians. The result is between -pi and pi. The vector in the plane from the origin to point (x, y) makes this angle with the positive X axis. The point of atan2() is that the signs of both inputs are known to it, so it can compute the correct quadrant for the angle. For example, atan(1) and atan2(1, 1) are both pi/4, but atan2(-1, -1) is -3*pi/4. 22 | 23 | The rotation(for x axis) is calculated using atan2 function. It calculates angle from length of y, z vectors. 57.2957795 is conversation of radian to degree. +180 is for offset. 24 | ''' 25 | 26 | from __future__ import print_function 27 | 28 | import gettext #Internationalization 29 | gettext.bindtextdomain("expeyes") 30 | gettext.textdomain('expeyes') 31 | _ = gettext.gettext 32 | 33 | 34 | import time, math, sys 35 | if sys.version_info.major==3: # Python 3 compatibility 36 | from tkinter import * 37 | else: 38 | from Tkinter import * 39 | 40 | sys.path=[".."] + sys.path 41 | 42 | 43 | from math import* # for using function atan2 44 | 45 | # from numpy import* 46 | import expeyes.eyesj as eyes 47 | import expeyes.eyeplot as eyeplot 48 | import expeyes.eyemath as eyemath 49 | p=eyes.open() 50 | 51 | 52 | 53 | print (p.set_voltage(3.6)) # set voltage at PVS 3.6v is operating voltage for ADXL335 54 | 55 | t,v = p.get_voltage_time(1) # Read A1 56 | v2 = p.get_voltage(2) # Read A2 57 | v3 = p.get_voltage(3) # Read IN1 58 | 59 | Xaccl = (v-1.6) / 0.3 60 | Yaccl = (v2-1.6) / 0.3 61 | Zaccl = (v3-1.6) / 0.3 62 | 63 | angle_x =atan2(-Yaccl,-Zaccl)*57.2957795+180; 64 | 65 | angle_y =atan2(-Zaccl,-Xaccl)*57.2957795+180; 66 | 67 | angle_z =atan2(-Xaccl,-Yaccl)*57.2957795+180; 68 | 69 | print ("Tilt angle X-axis = ", angle_x, "degree") 70 | print ("Tilt angle Y-axis = ", angle_y, "degree") 71 | print ("Tilt angle z-axis = ", angle_z, "degree") 72 | 73 | -------------------------------------------------------------------------------- /sensors/AccelerometerADXL335/acceleration-measurement.md: -------------------------------------------------------------------------------- 1 | ###Distinguishing Acceleration from Gravity 2 | 3 | ADXL335 sensor sense both dynamic acceleration due to movement and static acceleration due to gravity. The sensor returns a vector 4 | that can be written as: 5 | a_sensor=a_dynamic+a_gravity. 6 | 7 | When the accelerometer is at rest, 8 | a_dynamic=0. 9 | 10 | In this case the angle of a_gravity, which will always have a magnitude of 1g, can be used to calculate the orientation or tilt of the sensor. 11 | 12 | 13 | When the accelerometer is moving at a non-constant velocity, 14 | a_dynamic will be added to the sensor reading. If the orientation of the accelerometer is known and fixed, then 15 | a_gravity can be calculated (or measured when the sensor is at rest) and subtracted from 16 | a_sensor to isolate a_dynamic. 17 | 18 | 19 | Unfortunately, this is rarely the case. There is a heuristic technique that may be useful for estimating 20 | a_dynamic in cases where the orientation of the accelerometer is unknown and movement is sporadic. 21 | The magnitude of 22 | a_sensor is calculated as 23 | 24 | a_sensor= sqrt [(a_sensorX)^2 + (a_sensorY)^2 + (a_sensorZ)^2] 25 | 26 | 27 | 28 | If the magnitude of 29 | a_sensor is very close to 1g for prolonged periods of time, it is likely that a_dynamic is zero during these “rest times” 30 | (though they may also correspond to periods of movement at a constant velocity). 31 | 32 | If we assume that a_sensor is equal to a_gravity during these periods, then the orientation of the sensor may be updated to a new value. This 33 | estimate of a_gravity is then subtracted from all accelerometer readings until the next “rest time” where it can be 34 | reassessed. 35 | 36 | 37 | -------------------------------------------------------------------------------- /sensors/AccelerometerADXL335/acceleration-xyz.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI Program to plot acceleration data using ADXL335 sensor in real-time 3 | 4 | 5 | ExpEYES program developed as a part of GSoC-2015 project 6 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 7 | Mentor Organization:FOSSASIA 8 | Mentors: Hong Phuc, Mario Behling, Rebentisch 9 | Author: Praveen Patil 10 | License : GNU GPL version 3 11 | 12 | Calibration: 13 | For calculating acceleration in terms of g 14 | Ref: https://www.sparkfun.com/datasheets/Components/SMD/adxl335.pdf 15 | For 0g v = 1.61 volt 16 | -1g v = 1.31 volt 17 | +1g v = 1.91 volt 18 | Sensitivity 0.3v/g 19 | 20 | ''' 21 | from __future__ import print_function 22 | 23 | import gettext #Internationalization 24 | gettext.bindtextdomain("expeyes") 25 | gettext.textdomain('expeyes') 26 | _ = gettext.gettext 27 | 28 | 29 | import time, math, sys 30 | if sys.version_info.major==3: # Python 3 compatibility 31 | from tkinter import * 32 | else: 33 | from Tkinter import * 34 | 35 | sys.path=[".."] + sys.path 36 | 37 | import expeyes.eyesj as eyes 38 | import expeyes.eyeplot as eyeplot 39 | import expeyes.eyemath as eyemath 40 | 41 | 42 | 43 | WIDTH = 600 # width of drawing canvas 44 | HEIGHT = 400 # height 45 | 46 | class Accl: 47 | tv = [ [], [], [], [] ] # Three Lists for Readings time, v1, v2, v3 48 | TIMER = 5 # Time interval between reads 49 | MINY = -5 # Voltage range 50 | MAXY = 5 51 | running = False 52 | MAXTIME = 10 53 | VZERO = 1.6 # voltage at zero g 54 | SEN = 0.3 # sensitivity 0.3v/g 55 | 56 | 57 | def xmgrace(self): 58 | if self.running == True: 59 | return 60 | p.grace([self.tv]) 61 | 62 | def start(self): 63 | 64 | print (p.set_voltage(3.6)) # set voltage at PVS 3.6v is operating voltage for ADXL335 65 | self.running = True 66 | self.index = 0 67 | self.tv = [ [], [], [], [] ] 68 | try: 69 | 70 | self.MAXTIME = int(DURATION.get()) 71 | self.MINY = int(TMIN.get()) 72 | self.MAXY = int(TMAX.get()) 73 | 74 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('Acceleration g')) 75 | self.TIMER = int(TGAP.get()) 76 | Total.config(state=DISABLED) 77 | Dur.config(state=DISABLED) 78 | self.msg(_('Starting the Measurements')) 79 | root.after(self.TIMER, self.update) 80 | except: 81 | self.msg(_('Failed to Start')) 82 | pass 83 | 84 | def stop(self): 85 | self.running = False 86 | Dur.config(state=NORMAL) 87 | self.msg(_('User Stopped the measurements')) 88 | 89 | def update(self): 90 | if self.running == False: 91 | return 92 | t,v = p.get_voltage_time(1) # Read A1 93 | v2 = p.get_voltage(2) # Read A2 94 | v3 = p.get_voltage(3) # Read IN1 95 | 96 | Xaccl = (v-1.6) / 0.3 97 | Yaccl = (v2-1.6) / 0.3 98 | Zaccl = (v3-1.6) / 0.3 99 | # In the cases where the orientation of the accelerometer is unknown and movement is sporadic. 100 | #The magnitude of a_sensor is calculated as 101 | #a_sensor= sqrt [(a_sensorX)^2 + (a_sensorY)^2 + (a_sensorZ)^2] 102 | 103 | #accln_xyz = sqrt(Xaccl**2 +Yaccl**2 +Zaccl**2) 104 | 105 | if len(self.tv[0]) == 0: 106 | self.start_time = t 107 | elapsed = 0 108 | else: 109 | elapsed = t - self.start_time 110 | 111 | self.tv[0].append(elapsed) 112 | self.tv[1].append(Xaccl) 113 | self.tv[2].append(Yaccl) 114 | self.tv[3].append(Zaccl) 115 | 116 | if len(self.tv[0]) >= 2: 117 | g.delete_lines() 118 | g.line(self.tv[0], self.tv[1]) # Black line for x-axis 119 | g.line(self.tv[0], self.tv[2],1) # Red line for y-axis 120 | g.line(self.tv[0], self.tv[3],2) # Blue line for z-axis 121 | if elapsed > self.MAXTIME: 122 | self.running = False 123 | Total.config(state=NORMAL) 124 | Dur.config(state=NORMAL) 125 | self.msg(_('Completed the Measurements')) 126 | return 127 | root.after(self.TIMER, self.update) 128 | 129 | 130 | def save(self): 131 | try: 132 | fn = filename.get() 133 | except: 134 | fn = 'acceleration.dat' 135 | p.save([self.tv],fn) 136 | self.msg(_('Data saved to %s')%fn) 137 | 138 | def clear(self): 139 | if self.running == True: 140 | return 141 | self.tv = [ [], [], [], [] ] 142 | g.delete_lines() 143 | self.msg(_('Cleared Data and Trace')) 144 | 145 | def msg(self,s, col = 'blue'): 146 | msgwin.config(text=s, fg=col) 147 | def quit(self): 148 | sys.exit() 149 | 150 | p = eyes.open() 151 | p.disable_actions() 152 | root = Tk() 153 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 154 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) # make plot objects using draw.disp 155 | pen = Accl() 156 | 157 | cf = Frame(root, width = WIDTH, height = 10) 158 | cf.pack(side=TOP, fill = BOTH, expand = 1) 159 | 160 | 161 | b3 = Label(cf, text = _('Read Every')) 162 | b3.pack(side = LEFT, anchor = SW) 163 | TGAP = StringVar() 164 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 165 | TGAP.set('5') 166 | Dur.pack(side = LEFT, anchor = SW) 167 | b3 = Label(cf, text = _('mS,')) 168 | b3.pack(side = LEFT, anchor = SW) 169 | b3 = Label(cf, text = _('for total')) 170 | b3.pack(side = LEFT, anchor = SW) 171 | DURATION = StringVar() 172 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 173 | DURATION.set('10') 174 | Total.pack(side = LEFT, anchor = SW) 175 | b3 = Label(cf, text = _('Seconds.')) 176 | b3.pack(side = LEFT, anchor = SW) 177 | 178 | b3 = Label(cf, text = _('Range')) 179 | b3.pack(side = LEFT, anchor = SW) 180 | TMIN = StringVar() 181 | TMIN.set('-5') 182 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 183 | Tmin.pack(side = LEFT, anchor = SW) 184 | b3 = Label(cf, text = _('to,')) 185 | b3.pack(side = LEFT, anchor = SW) 186 | TMAX = StringVar() 187 | TMAX.set('5') 188 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 189 | Tmax.pack(side = LEFT, anchor = SW) 190 | b3 = Label(cf, text = _('C. ')) 191 | 192 | b3 = Button(cf, text = _('SAVE to'), command = pen.save) 193 | b3.pack(side = LEFT, anchor = SW) 194 | b3.pack(side = LEFT, anchor = SW) 195 | filename = StringVar() 196 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 197 | filename.set('acceleration.dat') 198 | e1.pack(side = LEFT, anchor = SW) 199 | 200 | cf = Frame(root, width = WIDTH, height = 10) 201 | cf.pack(side=TOP, fill = BOTH, expand = 1) 202 | 203 | b1 = Button(cf, text = _('Xmgrace'), command = pen.xmgrace) 204 | b1.pack(side = LEFT, anchor = SW) 205 | 206 | b3 = Label(cf, text = _(' Black Line : X-axis'), fg = 'black') 207 | b3.pack(side = LEFT, anchor = SW) 208 | b3 = Label(cf, text = _(' RED Line : Y-axis'), fg = 'red') 209 | b3.pack(side = LEFT, anchor = SW) 210 | b3 = Label(cf, text = _(' BLUE Line - Z-axis'), fg = 'blue') 211 | b3.pack(side = LEFT, anchor = SW) 212 | 213 | cf = Frame(root, width = WIDTH, height = 10) 214 | cf.pack(side=TOP, fill = BOTH, expand = 1) 215 | e1.pack(side = LEFT) 216 | 217 | 218 | b5 = Button(cf, text = _('QUIT'), command = pen.quit) 219 | b5.pack(side = RIGHT, anchor = N) 220 | b4 = Button(cf, text = _('CLEAR'), command = pen.clear) 221 | b4.pack(side = RIGHT, anchor = N) 222 | b1 = Button(cf, text = _('STOP'), command = pen.stop) 223 | b1.pack(side = RIGHT, anchor = N) 224 | b1 = Button(cf, text = _('START'), command = pen.start) 225 | b1.pack(side = RIGHT, anchor = N) 226 | 227 | 228 | mf = Frame(root, width = WIDTH, height = 10) 229 | mf.pack(side=TOP) 230 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 231 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 232 | 233 | root.title(_('EYESJUN: Accelerometer ADXL 335')) 234 | root.mainloop() 235 | -------------------------------------------------------------------------------- /sensors/AccelerometerADXL335/lissajous-accelerometer.py: -------------------------------------------------------------------------------- 1 | ''' 2 | expEYES lissajous program 3 | Developed as a part of GSoC Project "Plugins for ExpEYES" 4 | License : GNU GPL version 3 5 | 6 | connect AATINY85 module to IN1 and IN2 7 | black wire to GND 8 | Green is SQR input (pin 2) 9 | Red is output (pin 3) 10 | Module can be powered using USB or external USB adapter. 11 | the second module can be powered fron first from (P2VUSB pin) 12 | pin P1 can be touched to groung to RESET 13 | ''' 14 | import gettext 15 | gettext.bindtextdomain("expeyes") 16 | gettext.textdomain('expeyes') 17 | _ = gettext.gettext 18 | 19 | from Tkinter import * 20 | import expeyes.eyesj as eyes, expeyes.eyeplot as eyeplot, expeyes.eyemath as eyemath, time, math 21 | 22 | TIMER = 100 23 | WIDTH = 800 # width of drawing canvas 24 | HEIGHT = 400 # height 25 | delay = 50 # Time interval between samples 26 | NP = 450 # Number of samples 27 | data = [] # Of the form, [ [x1,y1], [x2,y2],....] where x and y are vectors 28 | outmask = 1 29 | looping = False 30 | 31 | 32 | def start(): 33 | global data,looping, NP, delay 34 | p.disable_actions() 35 | msec = int(Nsam.get()) 36 | if 1 <= msec <= 200: # total time 37 | delay = msec * 1000/ NP 38 | else: 39 | delay = 50 * 1000/NP 40 | print NP, delay, NP*delay 41 | g.setWorld(-5,-5, 5, 5,_('Volts'),_('Volts')) 42 | 43 | 44 | t,v,tt,vv = p.capture2_hr(3,4,NP,delay) 45 | g.delete_lines() 46 | g.line(v,vv) 47 | data.append([v,vv]) 48 | 49 | def save(): 50 | global data 51 | s = fn.get() 52 | if s == '': 53 | return 54 | p.save(data, s) 55 | msgwin.config(text = _('Data saved to file ')+s) 56 | 57 | def quit(): 58 | sys.exit() 59 | 60 | p = eyes.open() 61 | p.set_sqr1(0) 62 | 63 | root = Tk() 64 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 65 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT) # make plot objects using draw.disp 66 | g.setWorld(0,-5, NP * delay * 0.001, 5,_('mS'),_('V')) 67 | 68 | if p == None: 69 | g.text(0, 0,_('EYES Hardware Not Found. Check Connections and restart the program'),1) 70 | root.mainloop() 71 | sys.exit() 72 | 73 | cf = Frame(root, width = WIDTH, height = 10) 74 | cf.pack(side=TOP, fill = BOTH, expand = 1) 75 | 76 | l = Label(cf,text='Sampling Time =') 77 | l.pack(side=LEFT, anchor=SW) 78 | Nsam = Entry(cf,width = 4, bg = 'white') 79 | Nsam.pack(side=LEFT, anchor = SW) 80 | Nsam.insert(END,'50') 81 | l = Label(cf,text='mS') 82 | l.pack(side=LEFT, anchor=SW) 83 | 84 | l = Label(cf,text='SINE1=') 85 | l.pack(side=LEFT, anchor=SW) 86 | Freq0 = Entry(cf,width = 10, bg = 'white') 87 | Freq0.pack(side=LEFT, anchor = SW) 88 | Freq0.insert(END,'100') 89 | 90 | l = Label(cf,text='SINE2=') 91 | l.pack(side=LEFT, anchor=SW) 92 | Freq = Entry(cf,width = 10, bg = 'white') 93 | Freq.pack(side=LEFT, anchor = SW) 94 | Freq.insert(END,'200') 95 | 96 | Start = Button(cf,text =_('DRAW'), command = start, fg = 'blue') 97 | Start.pack(side=LEFT, anchor = SW) 98 | 99 | 100 | b = Button(cf,text =_('Save to'), command=save) 101 | b.pack(side=LEFT, anchor = SW) 102 | fn = Entry(cf,width = 10, bg = 'white') 103 | fn.pack(side=LEFT, anchor = SW) 104 | fn.insert(END,'lissajous.dat') 105 | b = Button(cf,text =_('QUIT'), command=quit) 106 | b.pack(side=RIGHT, anchor = SW) 107 | 108 | 109 | mf = Frame(root) # Message Frame below command frame. 110 | mf.pack(side=TOP, anchor = SW) 111 | msgwin = Label(mf,text = _('Messages'), fg = 'blue') 112 | msgwin.pack(side=LEFT, anchor = SW) 113 | 114 | 115 | eyeplot.pop_image('pics/lissa.png', _('Lissajous Figures')) 116 | root.title(_('EYES: Lissajous Figuresusing accelerometer')) 117 | root.mainloop() 118 | -------------------------------------------------------------------------------- /sensors/Battery-Characteristics/charging-discharging.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI Program to plot charging discharging curve for re-chargeable batteries in real-time 3 | 4 | 5 | ExpEYES program developed as a part of GSoC-2015 project 6 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 7 | Mentor Organization:FOSSASIA 8 | Mentors: Hong Phuc, Mario Behling, Rebentisch 9 | Author: Praveen Patil 10 | License : GNU GPL version 3 11 | ''' 12 | import gettext 13 | gettext.bindtextdomain("expeyes") 14 | gettext.textdomain('expeyes') 15 | _ = gettext.gettext 16 | 17 | import time, sys, math 18 | if sys.version_info.major==3: 19 | from tkinter import * 20 | else: 21 | from Tkinter import * 22 | 23 | sys.path=[".."] + sys.path 24 | 25 | import expeyes.eyesj as eyes 26 | import expeyes.eyeplot as eyeplot 27 | import expeyes.eyemath as eyemath 28 | 29 | 30 | TIMER = 100 31 | WIDTH = 500 # width of drawing canvas 32 | HEIGHT = 350 # height 33 | VPERDIV = 1.0 # Volts per division, vertical scale 34 | delay = 20 # Time interval between samples 35 | NP = 100 # Number of samples 36 | data = [ [], [] ] 37 | history = [] # Data store 38 | trial = 0 # trial number 39 | data = [ [], [] ] # Current & Voltage 40 | 41 | 42 | def capture(i): 43 | global data, history, trial 44 | s = '' 45 | if i == 0: # Take OD1 LOW. To HIGH before capture 46 | p.set_state(10,0) # OD1 to LOW 47 | p.enable_set_high(10) # enable HI on OD1 48 | elif i == 1: # Take OD1 HI. To HIGH before capture 49 | p.set_state(10,1) # OD1 to HI 50 | p.enable_set_low(10) # enable LO on OD1 51 | else: 52 | p.set_state(11,0) # CCS OFF 53 | time.sleep(0.5) 54 | p.enable_set_high(11) # enable HI on CCS 55 | time.sleep(0.5) 56 | t, v = p.capture_hr(1,NP,delay) 57 | g.line(t,v, trial) 58 | data = t,v 59 | history.append(data) 60 | trial += 1 61 | msgwin.config(text = _('Done')) 62 | 63 | def view_all(): 64 | global history 65 | g.delete_lines() 66 | c = 0 67 | for t,v in history: 68 | g.line(t,v,c) 69 | c += 1 70 | 71 | def fit_curve(): 72 | global data 73 | fa = eyemath.fit_exp(data[0], data[1]) 74 | if fa != None: 75 | pa = fa[1] 76 | rc = abs(1.0 / pa[1]) 77 | g.line(data[0],fa[0],1) 78 | dispmsg(_('RC = %5.2f mSec')%rc) 79 | else: 80 | dispmsg(_('Failed to fit the curve with V=Vo*exp(-t/RC)')) 81 | 82 | def dispmsg(s): 83 | msgwin.config(text=s) 84 | 85 | def clear(): 86 | global history, trial 87 | g.delete_lines() 88 | history = [] 89 | trial = 0 90 | 91 | def save(): 92 | global history 93 | s = fn.get() 94 | if s == '': 95 | return 96 | p.save(history, s) 97 | msgwin.config(text = _('Data saved to file ')+s) 98 | 99 | def xmgrace(): # Send the data to Xmgrace 100 | global history 101 | p.grace(history, _('milliSeconds'), _('Volts')) 102 | 103 | def set_timebase(w): 104 | global delay, NP, NC, VPERDIV 105 | divs = [0.050, 0.100, 0.200, 0.500, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0] 106 | msperdiv = divs[int(timebase.get())] 107 | totalusec = int(msperdiv * 1000 * 10) 108 | NP = 100 # Assume 100 samples to start with 109 | delay = int(totalusec/100) # Calculate delay 110 | if delay < 10: 111 | sf = 10/delay 112 | delay = 10 113 | NP = NP/sf 114 | elif delay > 1000: 115 | sf = delay/1000 116 | delay = 1000 117 | NP = NP * sf 118 | g.setWorld(0, 0*VPERDIV, NP * delay * 0.001, 5*VPERDIV,_('mS'),_('V')) 119 | 120 | p = eyes.open() 121 | root = Tk() 122 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 123 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) # make plot objects using draw.disp 124 | g.setWorld(0, 0, 20,5,_('V'),_('mA')) 125 | if p == None: 126 | g.text(0, 0,_('EYES Hardware Not Found. Check Connections and restart the program'),1) 127 | root.mainloop() 128 | sys.exit() 129 | 130 | cf = Frame(root, width = WIDTH, height = 10) 131 | cf.pack(side=TOP, fill = BOTH, expand = 1) 132 | 133 | l = Label(cf, text=_('mS/div')) 134 | l.pack(side=LEFT, anchor = SW ) 135 | timebase = Scale(cf,command = set_timebase, orient=HORIZONTAL, length=50, showvalue=False,\ 136 | from_ = 0, to=9, resolution=1) 137 | timebase.pack(side=LEFT, anchor = SW) 138 | timebase.set(3) 139 | b = Button(cf,text =_('0 to 5V STEP'), command= lambda i=0:capture(i)) 140 | b.pack(side=LEFT, anchor = SW) 141 | b = Button(cf,text =_('5 to 0V STEP'), command= lambda i=1:capture(i)) 142 | b.pack(side=LEFT, anchor = SW) 143 | b = Button(cf,text =_('CC Charge'), command= lambda i=2:capture(i)) 144 | b.pack(side=LEFT, anchor = SW) 145 | b = Button(cf,text =_('Calculate RC'), command=fit_curve) 146 | b.pack(side=LEFT, anchor = SW) 147 | b = Button(cf,text =_('QUIT'), command=sys.exit) 148 | b.pack(side=RIGHT, anchor = SW) 149 | 150 | cf = Frame(root, width = WIDTH, height = 10) 151 | cf.pack(side=TOP, fill = BOTH, expand = 1) 152 | b = Button(cf,text =_('ViewAll'), command=view_all) 153 | b.pack(side=LEFT, anchor = SW) 154 | b = Button(cf,text =_('Xmgrace'), command=xmgrace) 155 | b.pack(side=LEFT, anchor = SW) 156 | b4 = Button(cf, text = _('CLEAR'), command = clear) 157 | b4.pack(side = LEFT, anchor = N) 158 | b = Button(cf,text =_('Save to'), command=save) 159 | b.pack(side=LEFT, anchor = SW) 160 | fn = Entry(cf,width = 10, bg = 'white') 161 | fn.pack(side=LEFT, anchor = SW) 162 | fn.insert(END,'rc.dat') 163 | 164 | mf = Frame(root) # Message Frame below command frame. 165 | mf.pack(side=TOP) 166 | msgwin = Label(mf,text = '', fg = 'blue') 167 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH) 168 | 169 | eyeplot.pop_image('pics/xxxx.png', _('')) 170 | root.title(_('Battery Characteristics')) 171 | root.mainloop() 172 | 173 | -------------------------------------------------------------------------------- /sensors/Colour-Sensor/IC-TCS3200D-SOP8.md: -------------------------------------------------------------------------------- 1 | ###Color Sensor TCS3200D-TR TCS3200D SOP8 IC 2 | 3 | The TCS3200 programmable color light-to-frequency converters that combine configurable silicon photodiodes and a current-to-frequency converter on a single monolithic CMOS integrated circuit. 4 | The output is a square wave (50% duty cycle) with frequency directly proportional to light intensity (irradiance). 5 | 6 | *Interfacing with ExpEYES not yet done 7 | -------------------------------------------------------------------------------- /sensors/DC-motor-as-pickup-device/dc-motor-pickup.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI Program to use DC Motor as Pickup device 3 | 4 | ExpEYES program developed as a part of GSoC-2015 project 5 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 6 | Mentor Organization:FOSSASIA 7 | Mentors: Hong Phuc, Mario Behling, Rebentisch 8 | Author: Praveen Patil 9 | License : GNU GPL version 3 10 | ''' 11 | # Connections : Dc motor between GND and IN ( amplifier input pin) , OUT to A1 12 | # Get the output of DC motor amplified 13 | 14 | 15 | import gettext #Internationalization 16 | gettext.bindtextdomain("expeyes") 17 | gettext.textdomain('expeyes') 18 | _ = gettext.gettext 19 | 20 | import time, math, sys 21 | if sys.version_info.major==3: 22 | from tkinter import * 23 | else: 24 | from Tkinter import * 25 | 26 | sys.path=[".."] + sys.path 27 | 28 | import expeyes.eyesj as eyes 29 | import expeyes.eyeplot as eyeplot 30 | import expeyes.eyemath as eyemath 31 | 32 | WIDTH = 600 # width of drawing canvas 33 | HEIGHT = 400 # height 34 | 35 | class dcmotor: 36 | tv = [ [], [] ] # Three Lists for Readings time and v1 37 | TIMER = 5 # Time interval between reads 38 | MINY = -5 # Voltage range 39 | MAXY = 5 40 | running = False 41 | MAXTIME = 10 42 | 43 | def xmgrace(self): 44 | if self.running == True: 45 | return 46 | p.grace([self.tv]) 47 | 48 | def start(self): 49 | self.running = True 50 | self.index = 0 51 | self.tv = [ [], [] ] 52 | try: 53 | self.MAXTIME = int(DURATION.get()) 54 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('Volt')) 55 | Dur.config(state=DISABLED) 56 | self.msg(_('Starting the Measurements')) 57 | root.after(self.TIMER, self.update) 58 | except: 59 | self.msg(_('Failed to Start')) 60 | 61 | def stop(self): 62 | self.running = False 63 | Dur.config(state=NORMAL) 64 | self.msg(_('User Stopped the measurements')) 65 | 66 | def update(self): 67 | if self.running == False: 68 | return 69 | t,v = p.get_voltage_time(1) # Read A1 70 | if len(self.tv[0]) == 0: 71 | self.start_time = t 72 | elapsed = 0 73 | else: 74 | elapsed = t - self.start_time 75 | self.tv[0].append(elapsed) 76 | self.tv[1].append(v) 77 | if len(self.tv[0]) >= 2: 78 | g.delete_lines() 79 | g.line(self.tv[0], self.tv[1]) 80 | 81 | if elapsed > self.MAXTIME: 82 | self.running = False 83 | Dur.config(state=NORMAL) 84 | self.msg(_('Completed the Measurements')) 85 | return 86 | root.after(self.TIMER, self.update) 87 | 88 | def save(self): 89 | try: 90 | fn = filename.get() 91 | except: 92 | fn = 'dcmotor.dat' 93 | p.save([self.tv],fn) 94 | self.msg(_('Data saved to %s')%fn) 95 | 96 | def clear(self): 97 | if self.running == True: 98 | return 99 | self.tv = [ [], [] ] 100 | g.delete_lines() 101 | self.msg(_('Cleared Data and Trace')) 102 | 103 | def msg(self,s, col = 'blue'): 104 | msgwin.config(text=s, fg=col) 105 | 106 | p = eyes.open() 107 | p.disable_actions() 108 | root = Tk() 109 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 110 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) # make plot objects using draw.disp 111 | pen = dcmotor() 112 | 113 | cf = Frame(root, width = WIDTH, height = 10) 114 | cf.pack(side=TOP, fill = BOTH, expand = 1) 115 | 116 | 117 | b3 = Label(cf, text = _('Digitize for')) 118 | b3.pack(side = LEFT, anchor = SW) 119 | DURATION = StringVar() 120 | Dur =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 121 | DURATION.set('10') 122 | Dur.pack(side = LEFT, anchor = SW) 123 | b3 = Label(cf, text = _('Seconds.')) 124 | b3.pack(side = LEFT, anchor = SW) 125 | 126 | cf = Frame(root, width = WIDTH, height = 10) 127 | cf.pack(side=TOP, fill = BOTH, expand = 1) 128 | b1 = Button(cf, text = _('START'), command = pen.start) 129 | b1.pack(side = LEFT, anchor = N) 130 | b1 = Button(cf, text = _('STOP'), command = pen.stop) 131 | b1.pack(side = LEFT, anchor = N) 132 | b4 = Button(cf, text = _('CLEAR'), command = pen.clear) 133 | b4.pack(side = LEFT, anchor = N) 134 | b1 = Button(cf, text = _('Xmgrace'), command = pen.xmgrace) 135 | b1.pack(side = LEFT, anchor = N) 136 | b3 = Button(cf, text = _('SAVE to'), command = pen.save) 137 | b3.pack(side = LEFT, anchor = N) 138 | filename = StringVar() 139 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 140 | filename.set('dcmotor.dat') 141 | e1.pack(side = LEFT) 142 | b5 = Button(cf, text = _('QUIT'), command = sys.exit) 143 | b5.pack(side = RIGHT, anchor = N) 144 | 145 | mf = Frame(root, width = WIDTH, height = 10) 146 | mf.pack(side=TOP) 147 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 148 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 149 | 150 | 151 | eyeplot.pop_image('pics/image-name.png', _('')) # save the image in the same directory as of the program 152 | root.title(_('DC Motor as Pick-up Device')) 153 | root.mainloop() 154 | -------------------------------------------------------------------------------- /sensors/Electronic-Compass/3-axis-magnetic-sensor-GY271.md: -------------------------------------------------------------------------------- 1 | #### 3-axes Magnetic Field Sensor Module GY-271 2 | 3 | The Compass Module is designed for low-field magnetic sensing with a digital interface, to provide heading information for your microcontroller project. 4 | 5 | This compact sensor fits into small projects such as UAVs and robot navigation systems. The sensor converts any magnetic field to a differential voltage output on 3 axes. This voltage shift is the raw digital output value, 6 | which can then be used to calculate headings or sense magnetic fields coming from different directions. 7 | 8 | 9 | 10 | GY-271: HMC5883L Electronic Compass Module 11 | 12 | 3 Axis Magnetic Field Sensor 13 | 14 | Specs: 15 | 16 | High quality immersion gold pcb machine welding processes, quality assurance 17 | Name: HMC5883L module (three-axis magnetic field module) 18 | Model: GY-271 19 | Chip: HMC5883L 20 | Power supply 3-5v 21 | Means of communication: I2C communication protocol 22 | Measuring range: ± 1.3-8 Gauss 23 | 24 | -------------------------------------------------------------------------------- /sensors/Gas-Sensors/MQ-4.md: -------------------------------------------------------------------------------- 1 | ### MQ-4 Methane CNG gas sensor 2 | This methane gas sensor detects the concentration of methane gas in the air and ouputs its reading as an analog voltage. 3 | The concentration sensing range of 300 ppm to 10,000 ppm is suitable for leak detection. 4 | For example, the sensor could detect if someone left a gas stove on but not lit. 5 | The sensor can operate at temperatures from -10 to 50°C and consumes less than 150 mA at 5 V. 6 | 7 | 8 | 9 | This sensor has a high sensitivity and fast response time. The sensor's output is an analog resistance. 10 | -------------------------------------------------------------------------------- /sensors/Gas-Sensors/MQ-4.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI for interfacing LPG Gas Sensor MQ-4 with ExpEYES 3 | The GUI program is same for all gas sensors except the calibration factor 4 | to convert output voltage to gas concentartion in ppm. 5 | 6 | ExpEYES program developed as a part of GSoC-2015 project 7 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 8 | 9 | Mentor Organization:FOSSASIA 10 | Mentors: Hong Phuc, Mario Behling, Rebentisch 11 | Author: Praveen Patil 12 | License : GNU GPL version 3 13 | 14 | 15 | ''' 16 | 17 | #Connections vcc to OD1, GND to GND and AD to IN1 18 | 19 | import gettext 20 | gettext.bindtextdomain("expeyes") 21 | gettext.textdomain('expeyes') 22 | _ = gettext.gettext 23 | 24 | import time, math, sys 25 | if sys.version_info.major==3: 26 | from tkinter import * 27 | else: 28 | from Tkinter import * 29 | 30 | sys.path=[".."] + sys.path 31 | 32 | 33 | import expeyes.eyesj as eyes 34 | import expeyes.eyeplot as eyeplot 35 | import expeyes.eyemath as eyemath 36 | 37 | WIDTH = 600 # width of drawing canvas 38 | HEIGHT = 400 # height 39 | 40 | class MQ4: 41 | tv = [ [], [] ] # Lists for Readings 42 | TIMER = 10 # Time interval between reads 43 | MINY = 0 44 | MAXY = 5 45 | running = False 46 | 47 | 48 | def xmgrace(self): 49 | if self.running == True: 50 | return 51 | p.grace([self.tv]) 52 | 53 | def start(self): 54 | self.running = True 55 | self.index = 0 56 | self.tv = [ [], [] ] 57 | p.set_state (10,1) 58 | try: 59 | self.MAXTIME = int(DURATION.get()) 60 | self.MINY = int(TMIN.get()) 61 | self.MAXY = int(TMAX.get()) 62 | 63 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,'','') 64 | self.TIMER = int(TGAP.get()) 65 | Total.config(state=DISABLED) 66 | Dur.config(state=DISABLED) 67 | self.msg(_('Starting the Measurements')) 68 | root.after(self.TIMER, self.update) 69 | except: 70 | self.msg(_('Failed to Start')) 71 | 72 | def stop(self): 73 | self.running = False 74 | Total.config(state=NORMAL) 75 | Dur.config(state=NORMAL) 76 | self.msg(_('User Stopped the measurements')) 77 | #p.set_state (10,0) # added in def quit 78 | 79 | def update(self): 80 | if self.running == False: 81 | return 82 | t,v = p.get_voltage_time(3) # Read IN1 83 | if len(self.tv[0]) == 0: 84 | self.start_time = t 85 | elapsed = 0 86 | else: 87 | elapsed = t - self.start_time 88 | self.tv[0].append(elapsed) 89 | self.tv[1].append(v) 90 | 91 | if len(self.tv[0]) >= 2: 92 | g.delete_lines() 93 | 94 | g.line(self.tv[0], self.tv[1],1) 95 | 96 | if elapsed > self.MAXTIME: 97 | self.running = False 98 | Total.config(state=NORMAL) 99 | Dur.config(state=NORMAL) 100 | self.msg(_('Completed the Measurements')) 101 | return 102 | root.after(self.TIMER, self.update) 103 | 104 | 105 | def save(self): 106 | try: 107 | fn = filename.get() 108 | except: 109 | fn = 'MQ-4.dat' 110 | p.save([self.tv],fn) 111 | self.msg(_('Data saved to %s')%fn) 112 | 113 | def clear(self): 114 | if self.running == True: 115 | return 116 | self.nt = [ [], [] ] 117 | g.delete_lines() 118 | self.msg(_('Cleared Data and Trace')) 119 | 120 | def msg(self,s, col = 'blue'): 121 | msgwin.config(text=s, fg=col) 122 | 123 | def quit(self): 124 | p.set_state(10,0) 125 | sys.exit() 126 | 127 | p = eyes.open() 128 | p.disable_actions() 129 | 130 | root = Tk() 131 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 132 | 133 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 134 | pt = MQ4() 135 | 136 | cf = Frame(root, width = WIDTH, height = 10) 137 | cf.pack(side=TOP, fill = BOTH, expand = 1) 138 | 139 | b3 = Label(cf, text = _('Read Every')) 140 | b3.pack(side = LEFT, anchor = SW) 141 | TGAP = StringVar() 142 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 143 | TGAP.set('10') 144 | Dur.pack(side = LEFT, anchor = SW) 145 | b3 = Label(cf, text = _('mS,')) 146 | b3.pack(side = LEFT, anchor = SW) 147 | b3 = Label(cf, text = _('for total')) 148 | b3.pack(side = LEFT, anchor = SW) 149 | DURATION = StringVar() 150 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 151 | DURATION.set('100') 152 | Total.pack(side = LEFT, anchor = SW) 153 | b3 = Label(cf, text = _('Seconds.')) 154 | b3.pack(side = LEFT, anchor = SW) 155 | 156 | b3 = Label(cf, text = _('Range')) 157 | b3.pack(side = LEFT, anchor = SW) 158 | TMIN = StringVar() 159 | TMIN.set('0') 160 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 161 | Tmin.pack(side = LEFT, anchor = SW) 162 | b3 = Label(cf, text = _('to,')) 163 | b3.pack(side = LEFT, anchor = SW) 164 | TMAX = StringVar() 165 | TMAX.set('5') 166 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 167 | Tmax.pack(side = LEFT, anchor = SW) 168 | b3 = Label(cf, text = _('C. ')) 169 | 170 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 171 | b3.pack(side = LEFT, anchor = SW) 172 | b3.pack(side = LEFT, anchor = SW) 173 | filename = StringVar() 174 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 175 | filename.set('MQ-4.dat') 176 | e1.pack(side = LEFT, anchor = SW) 177 | 178 | cf = Frame(root, width = WIDTH, height = 10) 179 | cf.pack(side=TOP, fill = BOTH, expand = 1) 180 | 181 | b1 = Button(cf, text = _('Xmgrace'), command = pt.xmgrace) 182 | b1.pack(side = LEFT, anchor = SW) 183 | 184 | 185 | cf = Frame(root, width = WIDTH, height = 10) 186 | cf.pack(side=TOP, fill = BOTH, expand = 1) 187 | e1.pack(side = LEFT) 188 | 189 | 190 | 191 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 192 | b5.pack(side = RIGHT, anchor = N) 193 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 194 | b4.pack(side = RIGHT, anchor = N) 195 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 196 | b1.pack(side = RIGHT, anchor = N) 197 | b1 = Button(cf, text = _('START'), command = pt.start) 198 | b1.pack(side = RIGHT, anchor = N) 199 | 200 | mf = Frame(root, width = WIDTH, height = 10) 201 | mf.pack(side=TOP) 202 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 203 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 204 | 205 | root.title(_('MQ-4 Methane/Natural Gas Sensor')) 206 | root.mainloop() 207 | -------------------------------------------------------------------------------- /sensors/Gas-Sensors/MQ-6.md: -------------------------------------------------------------------------------- 1 | ### LPG sensor MQ-6 2 | 3 | This LPG Gas Sensor (MQ6), ideal sensor for use to detect the presence of a dangerous LPG leak in your Home, car, service station, storage tank environment or in a laboratory. This unit can be easily incorporated into an alarm unit, to sound an alarm or give a visual indication of the Combustible Gas / LPG concentration. The sensor has excellent sensitivity combined with a quick repsonse time. The sensor can also sense iso-butane, propane, LNG and cigarette smoke. This LPG Gas Sensor can be used to make wireless Gas leak detector in home security system. 4 | 5 | #### LPG Gas Sensor (MQ6) Features 6 | • High Sensitivity to LPG, iso-butane, propane 7 | • Small sensitivity to alcohol, smoke 8 | • Detection Range: 100 - 10,000 ppm iso-butane propane 9 | • Fast Response Time: <10s 10 | • Simple drive circuit 11 | • Heater Voltage: 5.0V 12 | • Dimensions: 18mm Diameter, 17mm High excluding pins, Pins - 6mm High 13 | 14 | #### Applications 15 | • Gas leak detection system 16 | • Fire/Safety detection system 17 | • Gas leak alarm 18 | • Gas detector 19 | -------------------------------------------------------------------------------- /sensors/Gas-Sensors/MQ-6.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI for interfacing LPG Gas Sensor MQ-6 with ExpEYES 3 | The GUI program is same for all gas sensors except the calibration factor 4 | to convert output voltage to gas concentartion in ppm. 5 | 6 | ExpEYES program developed as a part of GSoC-2015 project 7 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 8 | 9 | Mentor Organization:FOSSASIA 10 | Mentors: Hong Phuc, Mario Behling, Rebentisch 11 | Author: Praveen Patil 12 | License : GNU GPL version 3 13 | 14 | 15 | ''' 16 | 17 | #Connections vcc to OD1, GND to GND and AD to IN2 18 | 19 | import gettext 20 | gettext.bindtextdomain("expeyes") 21 | gettext.textdomain('expeyes') 22 | _ = gettext.gettext 23 | 24 | import time, math, sys 25 | if sys.version_info.major==3: 26 | from tkinter import * 27 | else: 28 | from Tkinter import * 29 | 30 | sys.path=[".."] + sys.path 31 | 32 | 33 | import expeyes.eyesj as eyes 34 | import expeyes.eyeplot as eyeplot 35 | import expeyes.eyemath as eyemath 36 | 37 | WIDTH = 600 # width of drawing canvas 38 | HEIGHT = 400 # height 39 | 40 | class MQ6: 41 | tv = [ [], [] ] # Lists for Readings 42 | TIMER = 10 # Time interval between reads 43 | MINY = 0 44 | MAXY = 5 45 | running = False 46 | 47 | 48 | def xmgrace(self): 49 | if self.running == True: 50 | return 51 | p.grace([self.tv]) 52 | 53 | def start(self): 54 | self.running = True 55 | self.index = 0 56 | self.tv = [ [], [] ] 57 | p.set_state (10,1) 58 | try: 59 | self.MAXTIME = int(DURATION.get()) 60 | self.MINY = int(TMIN.get()) 61 | self.MAXY = int(TMAX.get()) 62 | 63 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,'','') 64 | self.TIMER = int(TGAP.get()) 65 | Total.config(state=DISABLED) 66 | Dur.config(state=DISABLED) 67 | self.msg(_('Starting the Measurements')) 68 | root.after(self.TIMER, self.update) 69 | except: 70 | self.msg(_('Failed to Start')) 71 | 72 | def stop(self): 73 | self.running = False 74 | Total.config(state=NORMAL) 75 | Dur.config(state=NORMAL) 76 | self.msg(_('User Stopped the measurements')) 77 | #p.set_state (10,0) # added in def quit 78 | 79 | def update(self): 80 | if self.running == False: 81 | return 82 | t,v = p.get_voltage_time(4) # Read IN2 83 | if len(self.tv[0]) == 0: 84 | self.start_time = t 85 | elapsed = 0 86 | else: 87 | elapsed = t - self.start_time 88 | self.tv[0].append(elapsed) 89 | self.tv[1].append(v) 90 | 91 | if len(self.tv[0]) >= 2: 92 | g.delete_lines() 93 | 94 | g.line(self.tv[0], self.tv[1],1) 95 | 96 | if elapsed > self.MAXTIME: 97 | self.running = False 98 | Total.config(state=NORMAL) 99 | Dur.config(state=NORMAL) 100 | self.msg(_('Completed the Measurements')) 101 | return 102 | root.after(self.TIMER, self.update) 103 | 104 | 105 | def save(self): 106 | try: 107 | fn = filename.get() 108 | except: 109 | fn = 'MQ-6.dat' 110 | p.save([self.tv],fn) 111 | self.msg(_('Data saved to %s')%fn) 112 | 113 | def clear(self): 114 | if self.running == True: 115 | return 116 | self.nt = [ [], [] ] 117 | g.delete_lines() 118 | self.msg(_('Cleared Data and Trace')) 119 | 120 | def msg(self,s, col = 'blue'): 121 | msgwin.config(text=s, fg=col) 122 | 123 | def quit(self): 124 | p.set_state(10,0) 125 | sys.exit() 126 | 127 | p = eyes.open() 128 | p.disable_actions() 129 | 130 | root = Tk() 131 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 132 | 133 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 134 | pt = MQ6() 135 | 136 | cf = Frame(root, width = WIDTH, height = 10) 137 | cf.pack(side=TOP, fill = BOTH, expand = 1) 138 | 139 | b3 = Label(cf, text = _('Read Every')) 140 | b3.pack(side = LEFT, anchor = SW) 141 | TGAP = StringVar() 142 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 143 | TGAP.set('10') 144 | Dur.pack(side = LEFT, anchor = SW) 145 | b3 = Label(cf, text = _('mS,')) 146 | b3.pack(side = LEFT, anchor = SW) 147 | b3 = Label(cf, text = _('for total')) 148 | b3.pack(side = LEFT, anchor = SW) 149 | DURATION = StringVar() 150 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 151 | DURATION.set('100') 152 | Total.pack(side = LEFT, anchor = SW) 153 | b3 = Label(cf, text = _('Seconds.')) 154 | b3.pack(side = LEFT, anchor = SW) 155 | 156 | b3 = Label(cf, text = _('Range')) 157 | b3.pack(side = LEFT, anchor = SW) 158 | TMIN = StringVar() 159 | TMIN.set('0') 160 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 161 | Tmin.pack(side = LEFT, anchor = SW) 162 | b3 = Label(cf, text = _('to,')) 163 | b3.pack(side = LEFT, anchor = SW) 164 | TMAX = StringVar() 165 | TMAX.set('5') 166 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 167 | Tmax.pack(side = LEFT, anchor = SW) 168 | b3 = Label(cf, text = _('C. ')) 169 | 170 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 171 | b3.pack(side = LEFT, anchor = SW) 172 | b3.pack(side = LEFT, anchor = SW) 173 | filename = StringVar() 174 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 175 | filename.set('MQ-6.dat') 176 | e1.pack(side = LEFT, anchor = SW) 177 | 178 | cf = Frame(root, width = WIDTH, height = 10) 179 | cf.pack(side=TOP, fill = BOTH, expand = 1) 180 | 181 | b1 = Button(cf, text = _('Xmgrace'), command = pt.xmgrace) 182 | b1.pack(side = LEFT, anchor = SW) 183 | 184 | 185 | cf = Frame(root, width = WIDTH, height = 10) 186 | cf.pack(side=TOP, fill = BOTH, expand = 1) 187 | e1.pack(side = LEFT) 188 | 189 | 190 | 191 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 192 | b5.pack(side = RIGHT, anchor = N) 193 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 194 | b4.pack(side = RIGHT, anchor = N) 195 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 196 | b1.pack(side = RIGHT, anchor = N) 197 | b1 = Button(cf, text = _('START'), command = pt.start) 198 | b1.pack(side = RIGHT, anchor = N) 199 | 200 | mf = Frame(root, width = WIDTH, height = 10) 201 | mf.pack(side=TOP) 202 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 203 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 204 | 205 | root.title(_('MQ-6 LPG Gas Sensor')) 206 | root.mainloop() 207 | -------------------------------------------------------------------------------- /sensors/Gas-Sensors/MQ-7.md: -------------------------------------------------------------------------------- 1 | ### Carbon Monoxide Sensor MQ-7 2 | This Carbon Monoxide (CO) gas sensor detects the concentrations of CO in the air and ouputs its reading as an analog voltage. The sensor can measure concentrations of 10 to 10,000 ppm. 3 | The sensor can operate at temperatures from -10 to 50°C and consumes less than 150 mA at 5 V 4 | 5 | Datasheet Ref: https://www.sparkfun.com/datasheets/Sensors/Biometric/MQ-7.pdf 6 | -------------------------------------------------------------------------------- /sensors/Gas-Sensors/MQ-7.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI for interfacing Carbon Monoxide Gas Sensor MQ-7 with ExpEYES 3 | 4 | This GUI program is the same for all gas sensors except the calibration factor 5 | to convert output voltage to gas concentartion in ppm. 6 | 7 | 8 | ExpEYES program developed as a part of GSoC-2015 project 9 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 10 | 11 | Mentor Organization:FOSSASIA 12 | Mentors: Hong Phuc, Mario Behling, Rebentisch 13 | Author: Praveen Patil 14 | License : GNU GPL version 3 15 | 16 | 17 | ''' 18 | # Connections : VCC to OD1, GND to GND and AD to SEN 19 | 20 | 21 | import gettext 22 | gettext.bindtextdomain("expeyes") 23 | gettext.textdomain('expeyes') 24 | _ = gettext.gettext 25 | 26 | import time, math, sys 27 | if sys.version_info.major==3: 28 | from tkinter import * 29 | else: 30 | from Tkinter import * 31 | 32 | sys.path=[".."] + sys.path 33 | 34 | 35 | import expeyes.eyesj as eyes 36 | import expeyes.eyeplot as eyeplot 37 | import expeyes.eyemath as eyemath 38 | 39 | WIDTH = 600 # width of drawing canvas 40 | HEIGHT = 400 # height 41 | 42 | class MQ7: 43 | tv = [ [], [] ] # Lists for Readings 44 | TIMER = 10 # Time interval between reads 45 | MINY = 0 46 | MAXY = 5 47 | running = False 48 | 49 | 50 | def xmgrace(self): 51 | if self.running == True: 52 | return 53 | p.grace([self.tv]) 54 | 55 | def start(self): 56 | self.running = True 57 | self.index = 0 58 | self.tv = [ [], [] ] 59 | p.set_state (10,1) 60 | try: 61 | self.MAXTIME = int(DURATION.get()) 62 | self.MINY = int(TMIN.get()) 63 | self.MAXY = int(TMAX.get()) 64 | 65 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,'','') 66 | self.TIMER = int(TGAP.get()) 67 | Total.config(state=DISABLED) 68 | Dur.config(state=DISABLED) 69 | self.msg(_('Starting the Measurements')) 70 | root.after(self.TIMER, self.update) 71 | except: 72 | self.msg(_('Failed to Start')) 73 | 74 | def stop(self): 75 | self.running = False 76 | Total.config(state=NORMAL) 77 | Dur.config(state=NORMAL) 78 | self.msg(_('User Stopped the measurements')) 79 | 80 | def update(self): 81 | if self.running == False: 82 | return 83 | t,v = p.get_voltage_time(5) # Read SEN 84 | if len(self.tv[0]) == 0: 85 | self.start_time = t 86 | elapsed = 0 87 | else: 88 | elapsed = t - self.start_time 89 | self.tv[0].append(elapsed) 90 | self.tv[1].append(v) 91 | 92 | if len(self.tv[0]) >= 2: 93 | g.delete_lines() 94 | 95 | g.line(self.tv[0], self.tv[1],1) 96 | 97 | if elapsed > self.MAXTIME: 98 | self.running = False 99 | Total.config(state=NORMAL) 100 | Dur.config(state=NORMAL) 101 | self.msg(_('Completed the Measurements')) 102 | return 103 | root.after(self.TIMER, self.update) 104 | 105 | 106 | def save(self): 107 | try: 108 | fn = filename.get() 109 | except: 110 | fn = 'MQ-7.dat' 111 | p.save([self.tv],fn) 112 | self.msg(_('Data saved to %s')%fn) 113 | 114 | def clear(self): 115 | if self.running == True: 116 | return 117 | self.nt = [ [], [] ] 118 | g.delete_lines() 119 | self.msg(_('Cleared Data and Trace')) 120 | 121 | def msg(self,s, col = 'blue'): 122 | msgwin.config(text=s, fg=col) 123 | 124 | def quit(self): 125 | p.set_state(10,0) 126 | sys.exit() 127 | 128 | p = eyes.open() 129 | p.disable_actions() 130 | 131 | root = Tk() 132 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 133 | 134 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 135 | pt = MQ7() 136 | 137 | cf = Frame(root, width = WIDTH, height = 10) 138 | cf.pack(side=TOP, fill = BOTH, expand = 1) 139 | 140 | b3 = Label(cf, text = _('Read Every')) 141 | b3.pack(side = LEFT, anchor = SW) 142 | TGAP = StringVar() 143 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 144 | TGAP.set('10') 145 | Dur.pack(side = LEFT, anchor = SW) 146 | b3 = Label(cf, text = _('mS,')) 147 | b3.pack(side = LEFT, anchor = SW) 148 | b3 = Label(cf, text = _('for total')) 149 | b3.pack(side = LEFT, anchor = SW) 150 | DURATION = StringVar() 151 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 152 | DURATION.set('100') 153 | Total.pack(side = LEFT, anchor = SW) 154 | b3 = Label(cf, text = _('Seconds.')) 155 | b3.pack(side = LEFT, anchor = SW) 156 | 157 | b3 = Label(cf, text = _('Range')) 158 | b3.pack(side = LEFT, anchor = SW) 159 | TMIN = StringVar() 160 | TMIN.set('0') 161 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 162 | Tmin.pack(side = LEFT, anchor = SW) 163 | b3 = Label(cf, text = _('to,')) 164 | b3.pack(side = LEFT, anchor = SW) 165 | TMAX = StringVar() 166 | TMAX.set('5') 167 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 168 | Tmax.pack(side = LEFT, anchor = SW) 169 | b3 = Label(cf, text = _('C. ')) 170 | 171 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 172 | b3.pack(side = LEFT, anchor = SW) 173 | b3.pack(side = LEFT, anchor = SW) 174 | filename = StringVar() 175 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 176 | filename.set('MQ-7.dat') 177 | e1.pack(side = LEFT, anchor = SW) 178 | 179 | cf = Frame(root, width = WIDTH, height = 10) 180 | cf.pack(side=TOP, fill = BOTH, expand = 1) 181 | 182 | b1 = Button(cf, text = _('Xmgrace'), command = pt.xmgrace) 183 | b1.pack(side = LEFT, anchor = SW) 184 | 185 | 186 | cf = Frame(root, width = WIDTH, height = 10) 187 | cf.pack(side=TOP, fill = BOTH, expand = 1) 188 | e1.pack(side = LEFT) 189 | 190 | 191 | 192 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 193 | b5.pack(side = RIGHT, anchor = N) 194 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 195 | b4.pack(side = RIGHT, anchor = N) 196 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 197 | b1.pack(side = RIGHT, anchor = N) 198 | b1 = Button(cf, text = _('START'), command = pt.start) 199 | b1.pack(side = RIGHT, anchor = N) 200 | 201 | mf = Frame(root, width = WIDTH, height = 10) 202 | mf.pack(side=TOP) 203 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 204 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 205 | 206 | root.title(_('MQ-7 Carbon Monoxide Gas Sensor')) 207 | root.mainloop() 208 | -------------------------------------------------------------------------------- /sensors/Gas-Sensors/gas-sensors.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | ''' 4 | This GUI program is for detecting presence of various gases like Carbon Monoxide, Methane, LPG etc 5 | Plan is to have one common GUI for four different gas sensors 6 | ''' 7 | ''' 8 | GUI for interfacing LPG Gas Sensor MQ-4, MQ-6 and MQ-7 with ExpEYES 9 | 10 | ExpEYES program developed as a part of GSoC-2015 project 11 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 12 | 13 | Mentor Organization:FOSSASIA 14 | Mentors: Hong Phuc, Mario Behling, Rebentisch 15 | Author: Praveen Patil 16 | License : GNU GPL version 3 17 | 18 | 19 | 20 | Ref: For calculation of gas concentration in ppm : https://cdn.sparkfun.com/datasheets/Sensors/Biometric/MQ-7%20Ver1.3%20-%20Manual.pdf 21 | ''' 22 | 23 | #Connections vcc to OD1, GND to GND for all sensors 24 | #MQ-4 AD to IN1 25 | #MQ-6 AD to IN2 26 | #MQ-7 AD to SEN 27 | 28 | # Calibration to measure concentration in ppm is to be done 29 | 30 | import gettext 31 | gettext.bindtextdomain("expeyes") 32 | gettext.textdomain('expeyes') 33 | _ = gettext.gettext 34 | 35 | import time, math, sys 36 | if sys.version_info.major==3: 37 | from tkinter import * 38 | else: 39 | from Tkinter import * 40 | 41 | sys.path=[".."] + sys.path 42 | 43 | 44 | import expeyes.eyesj as eyes 45 | import expeyes.eyeplot as eyeplot 46 | import expeyes.eyemath as eyemath 47 | 48 | WIDTH = 600 # width of drawing canvas 49 | HEIGHT = 400 # height 50 | 51 | class MQ6: 52 | tv = [ [], [], [], [] ] # Lists for Readings 53 | TIMER = 10 # Time interval between reads 54 | MINY = 0 55 | MAXY = 5 56 | running = False 57 | 58 | 59 | def xmgrace(self): 60 | if self.running == True: 61 | return 62 | p.grace([self.tv]) 63 | 64 | def start(self): 65 | self.running = True 66 | self.index = 0 67 | self.tv = [ [], [], [], [] ] 68 | p.set_state (10,1) 69 | try: 70 | self.MAXTIME = int(DURATION.get()) 71 | self.MINY = int(TMIN.get()) 72 | self.MAXY = int(TMAX.get()) 73 | 74 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('Volt')) 75 | self.TIMER = int(TGAP.get()) 76 | Total.config(state=DISABLED) 77 | Dur.config(state=DISABLED) 78 | self.msg(_('Starting the Measurements')) 79 | root.after(self.TIMER, self.update) 80 | except: 81 | self.msg(_('Failed to Start')) 82 | 83 | def stop(self): 84 | self.running = False 85 | 86 | Total.config(state=NORMAL) 87 | Dur.config(state=NORMAL) 88 | p.set_state (10,0) 89 | self.msg(_('User Stopped the measurements')) 90 | 91 | def update(self): 92 | if self.running == False: 93 | return 94 | t,v = p.get_voltage_time(3) # Read IN1 95 | v1 = p.get_voltage(4) # Read IN2 96 | v2 = p.get_voltage(5) # Read SEN 97 | if len(self.tv[0]) == 0: 98 | self.start_time = t 99 | elapsed = 0 100 | else: 101 | elapsed = t - self.start_time 102 | self.tv[0].append(elapsed) 103 | self.tv[1].append(v) 104 | self.tv[2].append(v1) 105 | self.tv[3].append(v2) 106 | 107 | if len(self.tv[0]) >= 2: 108 | g.delete_lines() 109 | 110 | g.line(self.tv[0], self.tv[1]) # For MQ-4 111 | g.line(self.tv[0], self.tv[2],1) # For MQ-6 112 | g.line(self.tv[0], self.tv[3],2) # For MQ-7 113 | if elapsed > self.MAXTIME: 114 | self.running = False 115 | Total.config(state=NORMAL) 116 | Dur.config(state=NORMAL) 117 | self.msg(_('Completed the Measurements')) 118 | return 119 | root.after(self.TIMER, self.update) 120 | 121 | 122 | def save(self): 123 | try: 124 | fn = filename.get() 125 | except: 126 | fn = 'gas-sensors.dat' 127 | p.save([self.tv],fn) 128 | self.msg(_('Data saved to %s')%fn) 129 | 130 | def clear(self): 131 | if self.running == True: 132 | return 133 | self.nt = [ [], [] ] 134 | g.delete_lines() 135 | self.msg(_('Cleared Data and Trace')) 136 | 137 | def msg(self,s, col = 'blue'): 138 | msgwin.config(text=s, fg=col) 139 | 140 | def quit(self): 141 | p.set_state(10,0) 142 | sys.exit() 143 | 144 | p = eyes.open() 145 | p.disable_actions() 146 | 147 | root = Tk() 148 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 149 | 150 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 151 | pt = MQ6() 152 | 153 | cf = Frame(root, width = WIDTH, height = 10) 154 | cf.pack(side=TOP, fill = BOTH, expand = 1) 155 | 156 | b3 = Label(cf, text = _('Read Every')) 157 | b3.pack(side = LEFT, anchor = SW) 158 | TGAP = StringVar() 159 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 160 | TGAP.set('10') 161 | Dur.pack(side = LEFT, anchor = SW) 162 | b3 = Label(cf, text = _('mS,')) 163 | b3.pack(side = LEFT, anchor = SW) 164 | b3 = Label(cf, text = _('for total')) 165 | b3.pack(side = LEFT, anchor = SW) 166 | DURATION = StringVar() 167 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 168 | DURATION.set('100') 169 | Total.pack(side = LEFT, anchor = SW) 170 | b3 = Label(cf, text = _('Seconds.')) 171 | b3.pack(side = LEFT, anchor = SW) 172 | 173 | b3 = Label(cf, text = _('Range')) 174 | b3.pack(side = LEFT, anchor = SW) 175 | TMIN = StringVar() 176 | TMIN.set('0') 177 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 178 | Tmin.pack(side = LEFT, anchor = SW) 179 | b3 = Label(cf, text = _('to,')) 180 | b3.pack(side = LEFT, anchor = SW) 181 | TMAX = StringVar() 182 | TMAX.set('5') 183 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 184 | Tmax.pack(side = LEFT, anchor = SW) 185 | b3 = Label(cf, text = _('C. ')) 186 | 187 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 188 | b3.pack(side = LEFT, anchor = SW) 189 | b3.pack(side = LEFT, anchor = SW) 190 | filename = StringVar() 191 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 192 | filename.set('gas-sensors.dat') 193 | e1.pack(side = LEFT, anchor = SW) 194 | 195 | cf = Frame(root, width = WIDTH, height = 10) 196 | cf.pack(side=TOP, fill = BOTH, expand = 1) 197 | 198 | b1 = Button(cf, text = _('Xmgrace'), command = pt.xmgrace) 199 | b1.pack(side = LEFT, anchor = SW) 200 | 201 | 202 | cf = Frame(root, width = WIDTH, height = 10) 203 | cf.pack(side=TOP, fill = BOTH, expand = 1) 204 | e1.pack(side = LEFT) 205 | 206 | b3 = Label(cf, text = _(' Black Line - Methane'), fg = 'black') 207 | b3.pack(side = LEFT, anchor = SW) 208 | b3 = Label(cf, text = _(' Red Line - Liquified Petroium Gas'), fg = 'red') 209 | b3.pack(side = LEFT, anchor = SW) 210 | b3 = Label(cf, text = _(' Blue Line - Carbon Monoxide Gas'), fg = 'blue') 211 | b3.pack(side = LEFT, anchor = SW) 212 | 213 | 214 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 215 | b5.pack(side = RIGHT, anchor = N) 216 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 217 | b4.pack(side = RIGHT, anchor = N) 218 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 219 | b1.pack(side = RIGHT, anchor = N) 220 | b1 = Button(cf, text = _('START'), command = pt.start) 221 | b1.pack(side = RIGHT, anchor = N) 222 | 223 | mf = Frame(root, width = WIDTH, height = 10) 224 | mf.pack(side=TOP) 225 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 226 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 227 | 228 | root.title(_('ExpEYES: Gas Sensors GUI')) 229 | root.mainloop() 230 | -------------------------------------------------------------------------------- /sensors/Humidity-Sensor/HIH-4030.md: -------------------------------------------------------------------------------- 1 | ## HIH-4030 Analogue Humidity Sensor 2 | 3 | #### Decided to drop this sensor as the cost is high 18-10USD. I will be using HS1101 which is a low cost capacitive sensor. 4 | 5 | Description: This is a breakout board for Honeywell’s HIH-4030 humidity sensor. The HIH-4030 measures relative humidity (%RH) and delivers it as an analog output voltage. You can connect the output of the sensor directly to an ADC on a microcontroller; and, thanks to the sensor’s near linear voltage output, the data is very easy to process. 6 | 7 | Voltage applied to the supply pins should be within 4-5.8VDC, and optimally at 5V. The sensor will typically only consume about 200μA. 8 | 9 | This product comes as shown in the picture, with the HIH-4030 soldered onto the breakout board. The pins of the 3-pin header are spaced by 0.1". 10 | 11 | Features: 12 | 13 | Near linear, analog output 14 | 4-5.8VDC voltage supply 15 | All pins broken out to a 0.1" pitch header 16 | Laser trimmed interchangeability 17 | Low power design, typical current draw of only 200μA 18 | Enhanced accuracy 19 | Fast response time 20 | Stable, low drift performance 21 | -------------------------------------------------------------------------------- /sensors/Humidity-Sensor/HS1101-measurement.py: -------------------------------------------------------------------------------- 1 | ''' 2 | expEYES program developed as a part of GSoC-2015 project 3 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 4 | Mentor Organization:FOSSASIA 5 | Mentors: Hong Phuc, Mario Behling, Rebentisch 6 | Author: Praveen Patil 7 | License : GNU GPL version 3 8 | 9 | 10 | Program to convert capacitancein pF to relative humidity in % 11 | For Calculations this data sheet is used: 12 | https://www.parallax.com/sites/default/files/downloads/27920-Humidity-Sensor-Datasheet.pdf 13 | 14 | Slope of the curve and y-intercept is determined for 4 different linear sections of the response curve 15 | given in the data sheet using 16 | 17 | y=mx+c Here y is capacity ( cap) in pF and x is relative humidity (RH) in % and c is y-intercept 18 | m = dy/dx 19 | c =y-mx 20 | and 21 | x= (y-c)/m 22 | 23 | For Humidity 0% to 50% 24 | c= 163 in pF 25 | m = 0.3 26 | 27 | For Humidity 50% to 70% 28 | c= 160.25 in pF 29 | m = 0.375 30 | 31 | For Humidity 70% to 90% 32 | c= 156.75 in pF 33 | m = 0.425 34 | 35 | For Humidity 90% to 100% 36 | c= 136.5 in pF 37 | m = 0.65 38 | 39 | ''' 40 | #connect HS1011 between IN1 ans GND 41 | 42 | import expeyes.eyesj 43 | p= expeyes.eyesj.open() 44 | 45 | RH=-1 # default value for an error 46 | 47 | cap = p.measure_cap() 48 | if cap< 180: 49 | RH= (cap -163)/0.3 50 | elif 180= 2: 124 | g.delete_lines() 125 | 126 | g.line(self.tv[0], self.tv[1],1) # red line - Capacity in pF 127 | g.line(self.tv[0], self.tv[2],2) # blue line - Relative Humidity in % 128 | if elapsed > self.MAXTIME: 129 | self.running = False 130 | Total.config(state=NORMAL) 131 | Dur.config(state=NORMAL) 132 | self.msg(_('Completed the Measurements')) 133 | return 134 | root.after(self.TIMER, self.update) 135 | 136 | 137 | def save(self): 138 | try: 139 | fn = filename.get() 140 | except: 141 | fn = 'Humidiy.dat' 142 | p.save([self.tv],fn) 143 | self.msg(_('Data saved to %s')%fn) 144 | 145 | def clear(self): 146 | if self.running == True: 147 | return 148 | self.nt = [ [], [] ] 149 | g.delete_lines() 150 | self.msg(_('Cleared Data and Trace')) 151 | 152 | def msg(self,s, col = 'blue'): 153 | msgwin.config(text=s, fg=col) 154 | 155 | def quit(self): 156 | #p.set_state(10,0) 157 | sys.exit() 158 | 159 | p = eyes.open() 160 | p.disable_actions() 161 | 162 | root = Tk() 163 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 164 | 165 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 166 | pt = humidity() 167 | 168 | cf = Frame(root, width = WIDTH, height = 10) 169 | cf.pack(side=TOP, fill = BOTH, expand = 1) 170 | 171 | b3 = Label(cf, text = _('Read Every')) 172 | b3.pack(side = LEFT, anchor = SW) 173 | TGAP = StringVar() 174 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 175 | TGAP.set('2000') 176 | Dur.pack(side = LEFT, anchor = SW) 177 | b3 = Label(cf, text = _('mS,')) 178 | b3.pack(side = LEFT, anchor = SW) 179 | b3 = Label(cf, text = _('for total')) 180 | b3.pack(side = LEFT, anchor = SW) 181 | DURATION = StringVar() 182 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 183 | DURATION.set('100') 184 | Total.pack(side = LEFT, anchor = SW) 185 | b3 = Label(cf, text = _('Seconds.')) 186 | b3.pack(side = LEFT, anchor = SW) 187 | 188 | 189 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 190 | b3.pack(side = LEFT, anchor = N) 191 | #b3.pack(side = LEFT, anchor = SW) 192 | filename = StringVar() 193 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 194 | filename.set('Humidity.dat') 195 | e1.pack(side = RIGHT, anchor = SW) 196 | 197 | cf = Frame(root, width = WIDTH, height = 10) 198 | cf.pack(side=TOP, fill = BOTH, expand = 1) 199 | 200 | 201 | cf = Frame(root, width = WIDTH, height = 10) 202 | cf.pack(side=TOP, fill = BOTH, expand = 1) 203 | e1.pack(side = LEFT) 204 | 205 | 206 | b3 = Label(cf, text = _(' RED Line - Capacity in pF'), fg = 'red') 207 | b3.pack(side = LEFT, anchor = SW) 208 | b3 = Label(cf, text = _(' BLUE Line - Relative Humidity in %.'), fg = 'blue') 209 | b3.pack(side = LEFT, anchor = SW) 210 | 211 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 212 | b5.pack(side = RIGHT, anchor = N) 213 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 214 | b4.pack(side = RIGHT, anchor = N) 215 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 216 | b1.pack(side = RIGHT, anchor = N) 217 | b1 = Button(cf, text = _('START'), command = pt.start) 218 | b1.pack(side = RIGHT, anchor = N) 219 | 220 | mf = Frame(root, width = WIDTH, height = 10) 221 | mf.pack(side=TOP) 222 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 223 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 224 | 225 | root.title(_('Relative Humidity using HS-1101 sensor')) 226 | root.mainloop() 227 | -------------------------------------------------------------------------------- /sensors/Infra-red-Object-Sensor/IR-object-sensor.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI for interfacing IR object sensor with ExpEYES 3 | 4 | ExpEYES program developed as a part of GSoC-2015 project 5 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 6 | 7 | Mentor Organization:FOSSASIA 8 | Mentors: Hong Phuc, Mario Behling, Rebentisch 9 | Author: Praveen Patil 10 | License : GNU GPL version 3 11 | 12 | 13 | ''' 14 | # Connections : 5V to OD1, GND to GND and AOUT to SEN 15 | 16 | 17 | import gettext 18 | gettext.bindtextdomain("expeyes") 19 | gettext.textdomain('expeyes') 20 | _ = gettext.gettext 21 | 22 | import time, math, sys 23 | if sys.version_info.major==3: 24 | from tkinter import * 25 | else: 26 | from Tkinter import * 27 | 28 | sys.path=[".."] + sys.path 29 | 30 | 31 | import expeyes.eyesj as eyes 32 | import expeyes.eyeplot as eyeplot 33 | import expeyes.eyemath as eyemath 34 | 35 | WIDTH = 600 # width of drawing canvas 36 | HEIGHT = 400 # height 37 | 38 | class IRO: 39 | tv = [ [], [] ] # Lists for Readings 40 | TIMER = 10 # Time interval between reads 41 | MINY = 0 42 | MAXY = 5 43 | running = False 44 | 45 | 46 | def xmgrace(self): 47 | if self.running == True: 48 | return 49 | p.grace([self.tv]) 50 | 51 | def start(self): 52 | self.running = True 53 | self.index = 0 54 | self.tv = [ [], [] ] 55 | p.set_state (10,1) 56 | try: 57 | self.MAXTIME = int(DURATION.get()) 58 | self.MINY = int(TMIN.get()) 59 | self.MAXY = int(TMAX.get()) 60 | 61 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('Volt')) 62 | self.TIMER = int(TGAP.get()) 63 | Total.config(state=DISABLED) 64 | Dur.config(state=DISABLED) 65 | self.msg(_('Starting the Measurements')) 66 | root.after(self.TIMER, self.update) 67 | except: 68 | self.msg(_('Failed to Start')) 69 | 70 | def stop(self): 71 | self.running = False 72 | Total.config(state=NORMAL) 73 | Dur.config(state=NORMAL) 74 | self.msg(_('User Stopped the measurements')) 75 | 76 | def update(self): 77 | if self.running == False: 78 | return 79 | t,v = p.get_voltage_time(5) # Read SEN 80 | if len(self.tv[0]) == 0: 81 | self.start_time = t 82 | elapsed = 0 83 | else: 84 | elapsed = t - self.start_time 85 | self.tv[0].append(elapsed) 86 | self.tv[1].append(v) 87 | 88 | if len(self.tv[0]) >= 2: 89 | g.delete_lines() 90 | 91 | g.line(self.tv[0], self.tv[1],1) 92 | 93 | if elapsed > self.MAXTIME: 94 | self.running = False 95 | Total.config(state=NORMAL) 96 | Dur.config(state=NORMAL) 97 | self.msg(_('Completed the Measurements')) 98 | return 99 | root.after(self.TIMER, self.update) 100 | 101 | 102 | def save(self): 103 | try: 104 | fn = filename.get() 105 | except: 106 | fn = 'IRO.dat' 107 | p.save([self.tv],fn) 108 | self.msg(_('Data saved to %s')%fn) 109 | 110 | def clear(self): 111 | if self.running == True: 112 | return 113 | self.nt = [ [], [] ] 114 | g.delete_lines() 115 | self.msg(_('Cleared Data and Trace')) 116 | 117 | def msg(self,s, col = 'blue'): 118 | msgwin.config(text=s, fg=col) 119 | 120 | def quit(self): 121 | p.set_state(10,0) 122 | sys.exit() 123 | 124 | p = eyes.open() 125 | p.disable_actions() 126 | 127 | root = Tk() 128 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 129 | 130 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 131 | pt = IRO() 132 | 133 | cf = Frame(root, width = WIDTH, height = 10) 134 | cf.pack(side=TOP, fill = BOTH, expand = 1) 135 | 136 | b3 = Label(cf, text = _('Read Every')) 137 | b3.pack(side = LEFT, anchor = SW) 138 | TGAP = StringVar() 139 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 140 | TGAP.set('10') 141 | Dur.pack(side = LEFT, anchor = SW) 142 | b3 = Label(cf, text = _('mS,')) 143 | b3.pack(side = LEFT, anchor = SW) 144 | b3 = Label(cf, text = _('for total')) 145 | b3.pack(side = LEFT, anchor = SW) 146 | DURATION = StringVar() 147 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 148 | DURATION.set('100') 149 | Total.pack(side = LEFT, anchor = SW) 150 | b3 = Label(cf, text = _('Seconds.')) 151 | b3.pack(side = LEFT, anchor = SW) 152 | 153 | b3 = Label(cf, text = _('Range')) 154 | b3.pack(side = LEFT, anchor = SW) 155 | TMIN = StringVar() 156 | TMIN.set('0') 157 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 158 | Tmin.pack(side = LEFT, anchor = SW) 159 | b3 = Label(cf, text = _('to,')) 160 | b3.pack(side = LEFT, anchor = SW) 161 | TMAX = StringVar() 162 | TMAX.set('5') 163 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 164 | Tmax.pack(side = LEFT, anchor = SW) 165 | b3 = Label(cf, text = _('C. ')) 166 | 167 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 168 | b3.pack(side = LEFT, anchor = SW) 169 | b3.pack(side = LEFT, anchor = SW) 170 | filename = StringVar() 171 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 172 | filename.set('IRO.dat') 173 | e1.pack(side = LEFT, anchor = SW) 174 | 175 | cf = Frame(root, width = WIDTH, height = 10) 176 | cf.pack(side=TOP, fill = BOTH, expand = 1) 177 | 178 | b1 = Button(cf, text = _('Xmgrace'), command = pt.xmgrace) 179 | b1.pack(side = LEFT, anchor = SW) 180 | 181 | 182 | cf = Frame(root, width = WIDTH, height = 10) 183 | cf.pack(side=TOP, fill = BOTH, expand = 1) 184 | e1.pack(side = LEFT) 185 | 186 | 187 | 188 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 189 | b5.pack(side = RIGHT, anchor = N) 190 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 191 | b4.pack(side = RIGHT, anchor = N) 192 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 193 | b1.pack(side = RIGHT, anchor = N) 194 | b1 = Button(cf, text = _('START'), command = pt.start) 195 | b1.pack(side = RIGHT, anchor = N) 196 | 197 | mf = Frame(root, width = WIDTH, height = 10) 198 | mf.pack(side=TOP) 199 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 200 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 201 | 202 | root.title(_('IR Object Sensor')) 203 | root.mainloop() 204 | -------------------------------------------------------------------------------- /sensors/Infra-red-Object-Sensor/Object-sensor.md: -------------------------------------------------------------------------------- 1 | ### Infra-red Object Sensor 2 | The IR Object Detection sensor module is made using following components. 3 | - IR LED TSFF5210 4 | - PR (photodiode) BPV10NF 5 | - 1k resistance 6 | - 220E resistance 7 | - 6k8 resistance 8 | - 10k potentiometer 9 | - IC LM358 10 | 11 | This sensor is a low cost - low range infrared object detection module that one can easily make at home using IR LED's. 12 | The Main concept is simple, the IR led keeps transmitting IR infrared rays up to some range (there is a potentiometer also in the design with the help of which you can alter the range). 13 | When some object comes in the (IR) infrared range, the IR waves hits the object and comes back at some angle, 14 | The Photo diode next to IR led detects that IR infrared rays which got reflected from the object and hence works as a proximity sensor 15 | 16 | -------------------------------------------------------------------------------- /sensors/Magnetic-Field-Sensors/Hall-Effect-Sensor.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Hall Effect Sensor 4 | 5 | A Hall effect sensor is a transducer that varies its output voltage in response to a magnetic field. Hall effect sensors are used for proximity switching, positioning, speed detection, and current sensing applications.[1] 6 | 7 | In its simplest form, the sensor operates as an analog transducer, directly returning a voltage. With a known magnetic field, its distance from the Hall plate can be determined. 8 | Source : https://en.wikipedia.org/wiki/Hall_effect_sensor 9 | 10 | This is a cost-effective and highly functional hall-effect sensor. Very easy to interface with all microcontrollers and are used for proximity switching, positioning, speed detection, and current sensing applications. 11 | 3.5V to 12V DC operation voltage 12 | Low current consumption 13 | Temperature compensation 14 | Wide operating voltage range 15 | Open-Collector pre-driver 16 | 50mA maximum sinking output current 17 | Reverse polarity protection 18 | Lead Free Package: TO-92 19 | 20 | ###Data sheet of 3144 hall effect sensor 21 | http://www.elecrow.com/download/A3141-2-3-4-Datasheet.pdf 22 | -------------------------------------------------------------------------------- /sensors/Magnetic-Field-Sensors/KY-003-sensor.md: -------------------------------------------------------------------------------- 1 | ### KY-003 Hall Magnetic Sensor Module 2 | A Hall effect sensor is a transducer that varies its output voltage in response to a magnetic field. 3 | Hall effect sensors can be used for a range of measurement functions including proximity switching, positioning, 4 | speed detection, and current sensing applications. 5 | 6 | The KY-003 is a magnetic switch. If no magnetic field is present, the signal line of the sensor is HIGH (3.5 V). If a magnetic field is presented to the sensor, the signal line goes LOW, at the same time the LED on the sensor lights up. The polarity of the magnetic field is of influence to the switching action. 7 | The front side of the sensor needs the opposite polarity as the back of the sensor to switch on. 8 | ![ky003-1](https://cloud.githubusercontent.com/assets/7612306/9290066/fc860470-43a1-11e5-8ce6-255306e6f4ff.png) 9 | -------------------------------------------------------------------------------- /sensors/Magnetic-Field-Sensors/KY-003-switching.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI for using KY-003 Hall Magnetic Sensor as Switching Device/Magnetic field detector 3 | 4 | 5 | ExpEYES program developed as a part of GSoC-2015 project 6 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 7 | 8 | Mentor Organization:FOSSASIA 9 | Mentors: Hong Phuc, Mario Behling, Rebentisch 10 | Author: Praveen Patil 11 | License : GNU GPL version 3 12 | 13 | 14 | ''' 15 | 16 | #connections KY-003: Pin1 to GND, Pin 2 to OD1 and Pin 3 to A1 17 | 18 | import gettext 19 | gettext.bindtextdomain("expeyes") 20 | gettext.textdomain('expeyes') 21 | _ = gettext.gettext 22 | 23 | import time, math, sys 24 | if sys.version_info.major==3: 25 | from tkinter import * 26 | else: 27 | from Tkinter import * 28 | 29 | sys.path=[".."] + sys.path 30 | 31 | 32 | import expeyes.eyesj as eyes 33 | import expeyes.eyeplot as eyeplot 34 | import expeyes.eyemath as eyemath 35 | 36 | WIDTH = 600 # width of drawing canvas 37 | HEIGHT = 400 # height 38 | 39 | class KY003: 40 | tv = [ [], [] ] # Lists for Readings 41 | TIMER = 10 # Time interval between reads 42 | MINY = 0 43 | MAXY = 5 44 | running = False 45 | 46 | 47 | def xmgrace(self): 48 | if self.running == True: 49 | return 50 | p.grace([self.tv]) 51 | 52 | def start(self): 53 | self.running = True 54 | self.index = 0 55 | self.tv = [ [], [] ] 56 | p.set_state (10,1) 57 | try: 58 | self.MAXTIME = int(DURATION.get()) 59 | self.MINY = int(TMIN.get()) 60 | self.MAXY = int(TMAX.get()) 61 | 62 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('volt')) 63 | self.TIMER = int(TGAP.get()) 64 | Total.config(state=DISABLED) 65 | Dur.config(state=DISABLED) 66 | self.msg(_('Starting the Measurements')) 67 | root.after(self.TIMER, self.update) 68 | except: 69 | self.msg(_('Failed to Start')) 70 | 71 | def stop(self): 72 | self.running = False 73 | Total.config(state=NORMAL) 74 | Dur.config(state=NORMAL) 75 | self.msg(_('User Stopped the measurements')) 76 | 77 | def update(self): 78 | if self.running == False: 79 | return 80 | t,v = p.get_voltage_time(1) # Read A1 81 | if len(self.tv[0]) == 0: 82 | self.start_time = t 83 | elapsed = 0 84 | else: 85 | elapsed = t - self.start_time 86 | self.tv[0].append(elapsed) 87 | self.tv[1].append(v) 88 | 89 | if len(self.tv[0]) >= 2: 90 | g.delete_lines() 91 | 92 | g.line(self.tv[0], self.tv[1],1) 93 | 94 | if elapsed > self.MAXTIME: 95 | self.running = False 96 | Total.config(state=NORMAL) 97 | Dur.config(state=NORMAL) 98 | self.msg(_('Completed the Measurements')) 99 | return 100 | root.after(self.TIMER, self.update) 101 | 102 | 103 | def save(self): 104 | try: 105 | fn = filename.get() 106 | except: 107 | fn = 'KY-003.dat' 108 | p.save([self.tv],fn) 109 | self.msg(_('Data saved to %s')%fn) 110 | 111 | def clear(self): 112 | if self.running == True: 113 | return 114 | self.nt = [ [], [] ] 115 | g.delete_lines() 116 | self.msg(_('Cleared Data and Trace')) 117 | 118 | def msg(self,s, col = 'blue'): 119 | msgwin.config(text=s, fg=col) 120 | 121 | def quit(self): 122 | p.set_state(10,0) 123 | sys.exit() 124 | 125 | p = eyes.open() 126 | p.disable_actions() 127 | 128 | root = Tk() 129 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 130 | 131 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 132 | pt = KY003() 133 | 134 | cf = Frame(root, width = WIDTH, height = 10) 135 | cf.pack(side=TOP, fill = BOTH, expand = 1) 136 | 137 | b3 = Label(cf, text = _('Read Every')) 138 | b3.pack(side = LEFT, anchor = SW) 139 | TGAP = StringVar() 140 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 141 | TGAP.set('10') 142 | Dur.pack(side = LEFT, anchor = SW) 143 | b3 = Label(cf, text = _('mS,')) 144 | b3.pack(side = LEFT, anchor = SW) 145 | b3 = Label(cf, text = _('for total')) 146 | b3.pack(side = LEFT, anchor = SW) 147 | DURATION = StringVar() 148 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 149 | DURATION.set('100') 150 | Total.pack(side = LEFT, anchor = SW) 151 | b3 = Label(cf, text = _('Seconds.')) 152 | b3.pack(side = LEFT, anchor = SW) 153 | 154 | b3 = Label(cf, text = _('Range')) 155 | b3.pack(side = LEFT, anchor = SW) 156 | TMIN = StringVar() 157 | TMIN.set('0') 158 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 159 | Tmin.pack(side = LEFT, anchor = SW) 160 | b3 = Label(cf, text = _('to,')) 161 | b3.pack(side = LEFT, anchor = SW) 162 | TMAX = StringVar() 163 | TMAX.set('5') 164 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 165 | Tmax.pack(side = LEFT, anchor = SW) 166 | b3 = Label(cf, text = _('C. ')) 167 | 168 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 169 | b3.pack(side = LEFT, anchor = SW) 170 | b3.pack(side = LEFT, anchor = SW) 171 | filename = StringVar() 172 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 173 | filename.set('KY-003.dat') 174 | e1.pack(side = LEFT, anchor = SW) 175 | 176 | cf = Frame(root, width = WIDTH, height = 10) 177 | cf.pack(side=TOP, fill = BOTH, expand = 1) 178 | 179 | b1 = Button(cf, text = _('Xmgrace'), command = pt.xmgrace) 180 | b1.pack(side = LEFT, anchor = SW) 181 | 182 | 183 | cf = Frame(root, width = WIDTH, height = 10) 184 | cf.pack(side=TOP, fill = BOTH, expand = 1) 185 | e1.pack(side = LEFT) 186 | 187 | b3 = Label(cf, text = _(' Output HIGH - Magnetic Field is NOT Present'), fg = 'red') 188 | b3.pack(side = LEFT, anchor = SW) 189 | b3 = Label(cf, text = _(' Output LOW - Magnetic Field is Present'), fg = 'blue') 190 | b3.pack(side = LEFT, anchor = SW) 191 | 192 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 193 | b5.pack(side = RIGHT, anchor = N) 194 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 195 | b4.pack(side = RIGHT, anchor = N) 196 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 197 | b1.pack(side = RIGHT, anchor = N) 198 | b1 = Button(cf, text = _('START'), command = pt.start) 199 | b1.pack(side = RIGHT, anchor = N) 200 | 201 | mf = Frame(root, width = WIDTH, height = 10) 202 | mf.pack(side=TOP) 203 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 204 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 205 | 206 | root.title(_('Hall Magnetic Sensor KY-003')) 207 | root.mainloop() 208 | -------------------------------------------------------------------------------- /sensors/Magnetic-Field-Sensors/hall-effect-sensor.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | ''' 3 | GUI for using Hall Magnetic sensor 4 | 5 | ExpEYES program developed as a part of GSoC-2015 project 6 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 7 | 8 | Mentor Organization:FOSSASIA 9 | Mentors: Hong Phuc, Mario Behling, Rebentisch 10 | Author: Praveen Patil 11 | License : GNU GPL version 3 12 | 13 | ''' 14 | 15 | import gettext 16 | gettext.bindtextdomain("expeyes") 17 | gettext.textdomain('expeyes') 18 | _ = gettext.gettext 19 | import time, math, sys 20 | if sys.version_info.major==3: 21 | from tkinter import * 22 | else: 23 | from Tkinter import * 24 | sys.path=[".."] + sys.path 25 | 26 | import expeyes.eyesj as eyes 27 | import expeyes.eyeplot as eyeplot 28 | import expeyes.eyemath as eyemath 29 | 30 | 31 | 32 | WIDTH = 600 # width of drawing canvas 33 | HEIGHT = 400 # height 34 | 35 | class hall: 36 | tv = [ [], [] ] # Lists for Readings time, v, 37 | TIMER = 5 # Time interval between reads 38 | MINY = -5 # Voltage range 39 | MAXY = 5 40 | running = False 41 | MAXTIME = 10 42 | 43 | 44 | def xmgrace(self): 45 | if self.running == True: 46 | return 47 | p.grace([self.tv]) 48 | 49 | def start(self): 50 | 51 | print (p.set_voltage(5.0)) 52 | self.running = True 53 | self.index = 0 54 | self.tv = [ [], [] ] 55 | try: 56 | self.MAXTIME = int(DURATION.get()) 57 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('m/s^2')) 58 | Dur.config(state=DISABLED) 59 | self.msg(_('Starting the Measurements')) 60 | root.after(self.TIMER, self.update) 61 | except: 62 | self.msg(_('Failed to Start')) 63 | 64 | def stop(self): 65 | self.running = False 66 | Dur.config(state=NORMAL) 67 | self.msg(_('User Stopped the measurements')) 68 | 69 | def update(self): 70 | if self.running == False: 71 | return 72 | t,v = p.get_voltage_time(1) # Read A1 73 | 74 | if len(self.tv[0]) == 0: 75 | self.start_time = t 76 | elapsed = 0 77 | else: 78 | elapsed = t - self.start_time 79 | self.tv[0].append(elapsed) 80 | self.tv[1].append(v) 81 | 82 | if len(self.tv[0]) >= 2: 83 | g.delete_lines() 84 | g.line(self.tv[0], self.tv[1]) 85 | 86 | if elapsed > self.MAXTIME: 87 | self.running = False 88 | Dur.config(state=NORMAL) 89 | self.msg(_('Completed the Measurements')) 90 | return 91 | root.after(self.TIMER, self.update) 92 | 93 | def save(self): 94 | try: 95 | fn = filename.get() 96 | except: 97 | fn = 'halleffect.dat' 98 | p.save([self.tv],fn) 99 | self.msg(_('Data saved to %s')%fn) 100 | 101 | def clear(self): 102 | if self.running == True: 103 | return 104 | self.tv = [ [], [] ] 105 | g.delete_lines() 106 | self.msg(_('Cleared Data and Trace')) 107 | 108 | def msg(self,s, col = 'blue'): 109 | msgwin.config(text=s, fg=col) 110 | 111 | p = eyes.open() 112 | p.disable_actions() 113 | root = Tk() 114 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 115 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) # make plot objects using draw.disp 116 | pen = hall() 117 | 118 | cf = Frame(root, width = WIDTH, height = 10) 119 | cf.pack(side=TOP, fill = BOTH, expand = 1) 120 | 121 | 122 | b3 = Label(cf, text = _('Digitize for')) 123 | b3.pack(side = LEFT, anchor = SW) 124 | DURATION = StringVar() 125 | Dur =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 126 | DURATION.set('10') 127 | Dur.pack(side = LEFT, anchor = SW) 128 | b3 = Label(cf, text = _('Seconds.')) 129 | b3.pack(side = LEFT, anchor = SW) 130 | b3 = Label(cf, text = _('........')) 131 | b3.pack(side = LEFT, anchor = SW) 132 | 133 | cf = Frame(root, width = WIDTH, height = 10) 134 | cf.pack(side=TOP, fill = BOTH, expand = 1) 135 | b1 = Button(cf, text = _('START'), command = pen.start) 136 | b1.pack(side = LEFT, anchor = N) 137 | b1 = Button(cf, text = _('STOP'), command = pen.stop) 138 | b1.pack(side = LEFT, anchor = N) 139 | b4 = Button(cf, text = _('CLEAR'), command = pen.clear) 140 | b4.pack(side = LEFT, anchor = N) 141 | b1 = Button(cf, text = _('Xmgrace'), command = pen.xmgrace) 142 | b1.pack(side = LEFT, anchor = N) 143 | b3 = Button(cf, text = _('SAVE to'), command = pen.save) 144 | b3.pack(side = LEFT, anchor = N) 145 | filename = StringVar() 146 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 147 | filename.set('halleffect.dat') 148 | e1.pack(side = LEFT) 149 | b5 = Button(cf, text = _('QUIT'), command = sys.exit) 150 | b5.pack(side = RIGHT, anchor = N) 151 | 152 | mf = Frame(root, width = WIDTH, height = 10) 153 | mf.pack(side=TOP) 154 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 155 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 156 | 157 | 158 | #eyeplot.pop_image('pics/imagename.png', _('write the name of expt setup image')) 159 | root.title(_('Magnetic field using Hall Sensor ')) 160 | root.mainloop() 161 | -------------------------------------------------------------------------------- /sensors/Photo-gate/photo-gate.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI for using Photo-gate with ExpEYES 3 | 4 | ExpEYES program developed as a part of GSoC-2015 project 5 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 6 | 7 | Mentor Organization:FOSSASIA 8 | Mentors: Hong Phuc, Mario Behling, Rebentisch 9 | Author: Praveen Patil 10 | License : GNU GPL version 3 11 | 12 | 13 | Connections: LED between GND and SQR1 and Photo-transister between SEN and GND 14 | ''' 15 | 16 | import gettext 17 | gettext.bindtextdomain("expeyes") 18 | gettext.textdomain('expeyes') 19 | _ = gettext.gettext 20 | 21 | 22 | import time, math, sys 23 | if sys.version_info.major==3: 24 | from tkinter import * 25 | else: 26 | from Tkinter import * 27 | 28 | sys.path=[".."] + sys.path 29 | 30 | import expeyes.eyesj as eyes 31 | import expeyes.eyeplot as eyeplot 32 | import expeyes.eyemath as eyemath 33 | 34 | WIDTH = 600 35 | HEIGHT = 400 36 | 37 | class photogate: 38 | nt = [ [], [] ] # Lists for Trial number & T 39 | TIMER = 5 40 | MINY = 0 # could be 0 41 | MAXY = 1500 42 | running = False 43 | index = 0 44 | nmax = 10 45 | 46 | def xmgrace(self): 47 | if self.running == True: 48 | return 49 | p.grace([self.nt]) 50 | 51 | def start(self): 52 | self.running = True 53 | self.index = 0 54 | self.nt = [ [], [] ] 55 | p.set_sqr1(0) # Switch on the LED 56 | self.nmax = int(NMAX.get()) 57 | self.msg(_('Starting the Measurements')) 58 | Result.delete(1.0, END) 59 | root.after(self.TIMER, self.update) 60 | 61 | def stop(self): 62 | p.set_sqr1(-1) 63 | self.running = False 64 | self.msg(_('User Stopped the measurements')) 65 | 66 | def update(self): 67 | if self.running == False: 68 | return 69 | t = p.multi_r2rtime(0,3) 70 | if t > 0: 71 | s = _('%5.1f mS\n') %(t*1.0e-3) 72 | #print s 73 | Result.insert(END, s) 74 | self.nt[0].append(self.index) 75 | self.nt[1].append(t*1.0e-3) 76 | self.index += 1 77 | if self.index > self.nmax: 78 | self.running = False 79 | p.set_sqr2(-1) 80 | self.msg(_('Completed the Measurements')) 81 | return 82 | else: 83 | self.running = False 84 | p.set_sqr2(-1) 85 | self.msg(_('Timeout Error. Check Connections'),'red') 86 | return 87 | root.after(self.TIMER, self.update) 88 | 89 | def save(self): 90 | try: 91 | fn = filename.get() 92 | except: 93 | fn = 'photogate.dat' 94 | p.save([self.nt],fn) 95 | self.msg(_('Data saved to %s')%fn) 96 | 97 | def clear(self): 98 | if self.running == True: 99 | return 100 | self.nt = [ [], [] ] 101 | Result.delete(1.0,END) 102 | self.msg(_('Cleared Data and Trace')) 103 | 104 | def msg(self,s, col = 'blue'): 105 | msgwin.config(text=s, fg=col) 106 | 107 | p = eyes.open() 108 | p.disable_actions() 109 | root = Tk() 110 | pen = photogate() 111 | top = Frame() 112 | top.pack(side=TOP) 113 | cf = Frame(top, width = WIDTH, height = 10) 114 | cf.pack(side=LEFT, fill = BOTH, expand = 1) 115 | 116 | b3 = Label(cf, text = _('Trials')) 117 | b3.pack(side = TOP, anchor = W) 118 | NMAX = StringVar() 119 | e1 =Entry(cf, width=5, bg = 'white', textvariable = NMAX) 120 | e1.pack(side = TOP, anchor = W) 121 | NMAX.set('10') 122 | b1 = Button(cf, text = _('START'), command = pen.start) 123 | b1.pack(side = TOP, anchor = W) 124 | b1 = Button(cf, text = _('STOP'), command = pen.stop) 125 | b1.pack(side = TOP, anchor = W) 126 | b4 = Button(cf, text = _('CLEAR'), command = pen.clear) 127 | b4.pack(side = TOP, anchor = W) 128 | b3 = Button(cf, text = _('SAVE to'), command = pen.save) 129 | b3.pack(side = TOP, anchor = W) 130 | filename = StringVar() 131 | e1 =Entry(cf, width=10, bg = 'white', textvariable = filename) 132 | filename.set('photogate.dat') 133 | e1.pack(side = TOP) 134 | b1 = Button(cf, text = _('Xmgrace'), command = pen.xmgrace) 135 | b1.pack(side = TOP, anchor = W) 136 | b5 = Button(cf, text = _('QUIT'), command = sys.exit) 137 | b5.pack(side = TOP, anchor = W) 138 | 139 | Result = Text(top, width=15, height=16) # make plot objects using draw.disp 140 | Result.pack(side=LEFT) 141 | 142 | mf = Frame(root, width = WIDTH, height = 10) 143 | mf.pack(side=TOP) 144 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 145 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 146 | 147 | eyeplot.pop_image('pics/xyz.png', _('xyz')) 148 | root.title(_('EYES Junior: Photogate')) 149 | root.mainloop() 150 | 151 | -------------------------------------------------------------------------------- /sensors/Piezoelectrie-Transducer/piezoelectric-transducer.md: -------------------------------------------------------------------------------- 1 | **A Piezoelectric transducer** is a device that uses the piezoelectric effect to measure pressure, acceleration, strain or force by converting them to an electrical charge 2 | 3 | These devices can be used both as sensors and actuators, so they're referred to as transducers, a term applied to any device that can convert one form of energy to another. The sensor turns mechanical energy into electric potential, and the actuator converts electrical energy into mechanical force or motion. 4 | 5 | The Piezoelectric material used here, ceramic lead zirconate titanate known as PZT has the ability to provide twice the voltage of Quartz under a given force. These transducers are simple, reliable, and very robust, and so find wide use in industry, medicine, and aero-space work. They're unaffected by external electromagnetic fields, and so can be used in applications where electronic sensors would fail. 6 | They are stable over a broad range of temperatures, but may be effected by long use at high temperatures. 7 | -------------------------------------------------------------------------------- /sensors/Piezoelectrie-Transducer/piezoelectric-transducer.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI Program for Piezo-electric Transducer- Can be used as a impact/force sensor 3 | 4 | 5 | ExpEYES program developed as a part of GSoC-2015 project 6 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 7 | Mentor Organization:FOSSASIA 8 | Mentors: Hong Phuc, Mario Behling, Rebentisch 9 | Author: Praveen Patil 10 | License : GNU GPL version 3 11 | 12 | 13 | ''' 14 | import gettext 15 | gettext.bindtextdomain("expeyes") 16 | gettext.textdomain('expeyes') 17 | _ = gettext.gettext 18 | 19 | from Tkinter import * 20 | import time, math, sys 21 | if sys.version_info.major==3: 22 | from tkinter import * 23 | else: 24 | from Tkinter import * 25 | 26 | sys.path=[".."] + sys.path 27 | 28 | 29 | 30 | 31 | import expeyes.eyesj as eyes 32 | import expeyes.eyeplot as eyeplot 33 | import expeyes.eyemath as eyemath 34 | 35 | WIDTH = 600 # width of drawing canvas 36 | HEIGHT = 400 # height 37 | 38 | class piezo: 39 | tv = [ [], [] ] # Lists for Readings 40 | TIMER = 10 # Time interval between reads 41 | MINY = 0 42 | MAXY = 5 43 | running = False 44 | 45 | 46 | def xmgrace(self): 47 | if self.running == True: 48 | return 49 | p.grace([self.tv]) 50 | 51 | def start(self): 52 | self.running = True 53 | self.index = 0 54 | self.tv = [ [], [] ] 55 | 56 | try: 57 | self.MAXTIME = int(DURATION.get()) 58 | self.MINY = int(TMIN.get()) 59 | self.MAXY = int(TMAX.get()) 60 | 61 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_(''),_('')) 62 | self.TIMER = int(TGAP.get()) 63 | Total.config(state=DISABLED) 64 | Dur.config(state=DISABLED) 65 | self.msg(_('Starting the Measurements')) 66 | root.after(self.TIMER, self.update) 67 | except: 68 | self.msg(_('Failed to Start')) 69 | 70 | def stop(self): 71 | self.running = False 72 | Total.config(state=NORMAL) 73 | Dur.config(state=NORMAL) 74 | self.msg(_('User Stopped the measurements')) 75 | 76 | def update(self): 77 | if self.running == False: 78 | return 79 | t,v = p.get_voltage_time(1) # Read A1 80 | if len(self.tv[0]) == 0: 81 | self.start_time = t 82 | elapsed = 0 83 | else: 84 | elapsed = t - self.start_time 85 | self.tv[0].append(elapsed) 86 | self.tv[1].append(v) 87 | 88 | if len(self.tv[0]) >= 2: 89 | g.delete_lines() 90 | 91 | g.line(self.tv[0], self.tv[1],1) 92 | 93 | if elapsed > self.MAXTIME: 94 | self.running = False 95 | Total.config(state=NORMAL) 96 | Dur.config(state=NORMAL) 97 | self.msg(_('Completed the Measurements')) 98 | return 99 | root.after(self.TIMER, self.update) 100 | 101 | 102 | def save(self): 103 | try: 104 | fn = filename.get() 105 | except: 106 | fn = 'pizzo.dat' 107 | p.save([self.tv],fn) 108 | self.msg(_('Data saved to %s')%fn) 109 | 110 | def clear(self): 111 | if self.running == True: 112 | return 113 | self.nt = [ [], [] ] 114 | g.delete_lines() 115 | self.msg(_('Cleared Data and Trace')) 116 | 117 | def msg(self,s, col = 'blue'): 118 | msgwin.config(text=s, fg=col) 119 | 120 | def quit(self): 121 | p.set_state(10,0) 122 | sys.exit() 123 | 124 | p = eyes.open() 125 | p.disable_actions() 126 | 127 | root = Tk() 128 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 129 | 130 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 131 | pt = piezo() 132 | 133 | cf = Frame(root, width = WIDTH, height = 10) 134 | cf.pack(side=TOP, fill = BOTH, expand = 1) 135 | 136 | b3 = Label(cf, text = _('Read Every')) 137 | b3.pack(side = LEFT, anchor = SW) 138 | TGAP = StringVar() 139 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 140 | TGAP.set('10') 141 | Dur.pack(side = LEFT, anchor = SW) 142 | b3 = Label(cf, text = _('mS,')) 143 | b3.pack(side = LEFT, anchor = SW) 144 | b3 = Label(cf, text = _('for total')) 145 | b3.pack(side = LEFT, anchor = SW) 146 | DURATION = StringVar() 147 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 148 | DURATION.set('100') 149 | Total.pack(side = LEFT, anchor = SW) 150 | b3 = Label(cf, text = _('Seconds.')) 151 | b3.pack(side = LEFT, anchor = SW) 152 | 153 | b3 = Label(cf, text = _('Range')) 154 | b3.pack(side = LEFT, anchor = SW) 155 | TMIN = StringVar() 156 | TMIN.set('0') 157 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 158 | Tmin.pack(side = LEFT, anchor = SW) 159 | b3 = Label(cf, text = _('to,')) 160 | b3.pack(side = LEFT, anchor = SW) 161 | TMAX = StringVar() 162 | TMAX.set('5') 163 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 164 | Tmax.pack(side = LEFT, anchor = SW) 165 | b3 = Label(cf, text = _('C. ')) 166 | 167 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 168 | b3.pack(side = LEFT, anchor = SW) 169 | b3.pack(side = LEFT, anchor = SW) 170 | filename = StringVar() 171 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 172 | filename.set('piezo.dat') 173 | e1.pack(side = LEFT, anchor = SW) 174 | 175 | cf = Frame(root, width = WIDTH, height = 10) 176 | cf.pack(side=TOP, fill = BOTH, expand = 1) 177 | 178 | b1 = Button(cf, text = _('Xmgrace'), command = pt.xmgrace) 179 | b1.pack(side = LEFT, anchor = SW) 180 | 181 | 182 | cf = Frame(root, width = WIDTH, height = 10) 183 | cf.pack(side=TOP, fill = BOTH, expand = 1) 184 | e1.pack(side = LEFT) 185 | 186 | 187 | 188 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 189 | b5.pack(side = RIGHT, anchor = N) 190 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 191 | b4.pack(side = RIGHT, anchor = N) 192 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 193 | b1.pack(side = RIGHT, anchor = N) 194 | b1 = Button(cf, text = _('START'), command = pt.start) 195 | b1.pack(side = RIGHT, anchor = N) 196 | 197 | mf = Frame(root, width = WIDTH, height = 10) 198 | mf.pack(side=TOP) 199 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 200 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 201 | 202 | root.title(_('Piezo-electric Transducer')) 203 | root.mainloop() 204 | -------------------------------------------------------------------------------- /sensors/Pressure-Sensor/PressureSensor.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | ''' 3 | A simple code to test pressure sensor SPD015AAsil by SMARTEC 4 | 5 | ExpEYES program developed as a part of GSoC-2015 project 6 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 7 | Mentor Organization:FOSSASIA 8 | Mentors: Hong Phuc, Mario Behling, Rebentisch 9 | Author: Praveen Patil 10 | License : GNU GPL version 3 11 | 12 | 13 | 14 | **Connections** 15 | Pin 1 and Pin 5 not connected 16 | Pin 2 VCC Connect to PVS of ExpEYES at +5V , Pin 3 Output to IN1 / A1 17 | Pin 4 GND Between pin 2 and 4 connect a 100nF capacitor 18 | Result needs to be calibrated. 19 | ''' 20 | 21 | from pylab import plot, show 22 | import expeyes.eyesj 23 | p=expeyes.eyesj.open() 24 | print (p.set_voltage(5.0) ) 25 | print (p.get_voltage(1)) 26 | t,v = p.capture(1,300,100) 27 | plot(t,v) 28 | show() 29 | -------------------------------------------------------------------------------- /sensors/Pressure-Sensor/about-pressure-sensors.md: -------------------------------------------------------------------------------- 1 | ## Pressure Sensors 2 | ### BMP180 Digital Barometric Pressure Sensor 3 | 4 | This precision sensor from Bosch is the best low-cost sensing solution for measuring barometric pressure and temperature. Because pressure changes with altitude you can also use it as an altimeter! The sensor is soldered onto a PCB with a 3.3V regulator, I2C level shifter and pull-up resistors on the I2C pins. 5 | 6 | The BMP180 is the next-generation of sensors from Bosch, and replaces the BMP085. The good news is that it is completely identical to the BMP085 in terms of firmware/software/interfacing - you can use our BMP085 tutorial and any example code/libraries as a drop-in replacement. 7 | 8 | This board is 5V compliant - a 3.3V regulator and a i2c level shifter circuit is included so you can use this sensor safely with 5V logic and power. 9 | 10 | Pressure range: 300~1100hPa (elevation 9000 m ~-500 m) 11 | 12 | Power supply voltage: 1.8V~3.6V (VDDA), 1.62V~3.6V (VDDD) LCC8 package: lead-free ceramic carrier package (LCC) 13 | Size: 3.6mmx3.8x0.93mm Low power consumption: 5 µA, in standard mode High accuracy: low-power mode, the resolution of 0.06hPa (0.5 m) 14 | 15 | High linearity mode, resolution of 0.03hPa (0.25 m) With temperature output I2C interface Temperature compensation 16 | 17 | -------------------------------------------------------------------------------- /sensors/Pressure-Sensor/barrometric-pressure-bmp180.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | ''' 3 | Reference Program for reading data from digital pressure sensor BMP180 4 | Can be used to measure pressure, temperature and altitude. 5 | 6 | # Modifications are required for reading with ExpEYES inputs 7 | 8 | ''' 9 | 10 | from numpy import int16 11 | import time 12 | 13 | class BMP180: 14 | ADDRESS = 0x77 15 | REG_CONTROL = 0xF4 16 | REG_RESULT = 0xF6 17 | CMD_TEMP = 0x2E 18 | CMD_P0 = 0x34 19 | CMD_P1 = 0x74 20 | CMD_P2 = 0xB4 21 | CMD_P3 = 0xF4 22 | oversampling=0 23 | NUMPLOTS=3 24 | def __init__(self,I2C): 25 | 26 | self.I2C = I2C 27 | 28 | self.MB = self.__readInt__(0xBA) 29 | 30 | self.c3 = 160.0 * pow(2,-15) * self.__readInt__(0xAE) 31 | self.c4 = pow(10,-3) * pow(2,-15) * self.__readUInt__(0xB0) 32 | self.b1 = pow(160,2) * pow(2,-30) * self.__readInt__(0xB6) 33 | self.c5 = (pow(2,-15) / 160) * self.__readUInt__(0xB2) 34 | self.c6 = self.__readUInt__(0xB4) 35 | self.mc = (pow(2,11) / pow(160,2)) * self.__readInt__(0xBC) 36 | self.md = self.__readInt__(0xBE) / 160.0 37 | self.x0 = self.__readInt__(0xAA) 38 | self.x1 = 160.0 * pow(2,-13) * self.__readInt__(0xAC) 39 | self.x2 = pow(160,2) * pow(2,-25) * self.__readInt__(0xB8) 40 | self.y0 = self.c4 * pow(2,15) 41 | self.y1 = self.c4 * self.c3 42 | self.y2 = self.c4 * self.b1 43 | self.p0 = (3791.0 - 8.0) / 1600.0 44 | self.p1 = 1.0 - 7357.0 * pow(2,-20) 45 | self.p2 = 3038.0 * 100.0 * pow(2,-36) 46 | self.T=25 47 | print ('calib:',self.c3,self.c4,self.b1,self.c5,self.c6,self.mc,self.md,self.x0,self.x1,self.x2,self.y0,self.y1,self.p0,self.p1,self.p2) 48 | self.params={'setOversampling':[0,1,2,3]} 49 | self.name='BMP180 Altimeter' 50 | self.initTemperature() 51 | self.readTemperature() 52 | self.initPressure() 53 | self.baseline=self.readPressure() 54 | 55 | def __readInt__(self,addr): 56 | return int16(self.__readUInt__(addr)) 57 | 58 | def __readUInt__(self,addr): 59 | vals = self.I2C.readBulk(self.ADDRESS,addr,2) 60 | v=1.*((vals[0]<<8)|vals[1]) 61 | return v 62 | 63 | def initTemperature(self): 64 | self.I2C.writeBulk(self.ADDRESS,[self.REG_CONTROL,self.CMD_TEMP]) 65 | time.sleep(0.005) 66 | 67 | def readTemperature(self): 68 | vals = self.I2C.readBulk(self.ADDRESS,self.REG_RESULT,2) 69 | if len(vals)==2: 70 | T = (vals[0] <<8 ) + vals[1] 71 | a = self.c5 * (T - self.c6) 72 | self.T = a + (self.mc / (a + self.md)) 73 | return self.T 74 | else: 75 | return False 76 | 77 | def setOversampling(self,num): 78 | self.oversampling=num 79 | 80 | def initPressure(self): 81 | os = [0x34,0x74,0xb4,0xf4] 82 | delays=[0.005,0.008,0.014,0.026] 83 | self.I2C.writeBulk(self.ADDRESS,[self.REG_CONTROL,os[self.oversampling] ]) 84 | time.sleep(delays[self.oversampling]) 85 | 86 | def readPressure(self): 87 | vals = self.I2C.readBulk(self.ADDRESS,self.REG_RESULT,3) 88 | if len(vals)==3: 89 | P = 1.*(vals[0] <<8) + vals[1] + (vals[2]/256.0) 90 | s = self.T - 25.0 91 | x = (self.x2 * pow(s,2)) + (self.x1 * s) + self.x0 92 | y = (self.y2 * pow(s,2)) + (self.y1 * s) + self.y0 93 | z = (P - x) / y 94 | self.P = (self.p2 * pow(z,2)) + (self.p1 * z) + self.p0 95 | return self.P 96 | else: 97 | return False 98 | 99 | def altitude(self): 100 | #baseline pressure needs to be provided 101 | return (44330.0*(1-pow(self.P/self.baseline,1/5.255))) 102 | 103 | def sealevel(self,P,A): 104 | ''' 105 | given a calculated pressure and altitude, return the sealevel 106 | ''' 107 | return(P/pow(1-(A/44330.0),5.255)) 108 | 109 | def getRaw(self): 110 | self.initTemperature() 111 | self.readTemperature() 112 | self.initPressure() 113 | self.readPressure() 114 | return [self.T,self.P,self.altitude()] 115 | 116 | -------------------------------------------------------------------------------- /sensors/Readme.md: -------------------------------------------------------------------------------- 1 | ### List of Sensor Plug-ins 2 | 3 | ####1. Accelerometer 4 | Sensor Used: ADXL 335 - Three axis 5 | ####2. Magnetic Field Sensor 6 | Sensors Used: KY 003, 3144 Hall Effect Sensor 7 | ####3. Infra-red Object Sensor 8 | Sensor Used: Locally Made using IC LM-358N 9 | ####4. Ultrasonic Position Sensor 10 | Sensor Used: SRF-05 HY, SRF-04 11 | ####5. Temperature Sensor 12 | Sensor Used: PT-100 and LM-35 13 | ####6. Humidity Sensor 14 | Sensor Used: DHT-11, HS-1101 15 | ####7. Pressure- Barometric 16 | Sensor Used: BMP180 Digital sensor 17 | ####8. Pressure 18 | Sensor Used: Pizzo Electric sensor 19 | ####9. Gas Sensors 20 | Sensor Used: MQ-4 for Methane 21 | MQ-6 for LPG 22 | MQ-7 for Carbon Monoxide 23 | ####10. Colour Sensor ( in progress) 24 | Sensor Used: IC-TCS3200D-SOP8 25 | ####11. Anemometer- Wind Speed 26 | Sensor Used: Home-made 27 | ####12. Wind Direction 28 | Sensor Used: Home-made 29 | ####13. Rotatory Motion Sensor 30 | Sensor Used: DC Motor and a pick-up coil 31 | ####14. Motion Sensor-Photo Gate 32 | Sensor Used: Photo Gate using Photo Diode 33 | ####15. Other devices used as sensors 34 | Solar Cells 35 | Induction coil 36 | condensor mic 37 | ATTINY-85 MCU used for sine wave generation 38 | Raspberry Pi 2 Model B for stand-alone weather station 39 | 40 | 41 | 42 | Details of sensor modules 43 | (To be updated...) 44 | 45 | ####Accelerometer Sensor : ADXL-335 46 | 47 | An accelerometer is a device that measures proper acceleration ("g-force"). Proper acceleration is not the same as coordinate acceleration (rate of change of velocity). For example, an accelerometer at rest on the surface of the Earth will measure an acceleration g= 9.81 m/s2 straight upwards. By contrast, accelerometers in free fall orbiting and accelerating due to the gravity of Earth will measure zero. 48 | 49 | **ADXL 335-GY-61** is a small, thin, low power, complete three-axis accelerometer voltage output through the signal conditioning at a minimum of full scale ± 3 g measurement range acceleration. It can measure the acceleration of gravity,and movement, shock or vibration due to dynamic acceleration. 50 | 51 | 52 | ####Relative Humidity Sensor : HS-1101 53 | 54 | Relative humidity is an important metric used in weather forecasts and reports, as it is an indicator of the likelihood of precipitation, dew, or fog. In hot summer weather, a rise in relative humidity increases the apparent temperature to humans (and other animals) by hindering the evaporation of perspiration from the skin. Ref: wikipedia.org 55 | 56 | 57 | **HS1101 sensor** consists of a capacitor which varies with relative humidity and is used in a 555 circuit to generate a pulse train of frequency related to relative humidity. The number of pulses over a one second period are counted and the RH is then calculated. 58 | 59 | Based on a unique capacitive cell, this relative humidity sensor is designed for high volume, cost sensitive applications such as office automation, automotive cabin air control, home appliances, and industrial process control systems. They are also useful in all applications where humidity compensation is needed. 60 | 61 | ####Temeprature Sensors : LM-35 and PT-100 62 | 63 | Platinum resistance thermometers (PRTs) offer excellent accuracy over a wide temperature range (from –200 to +850 °C). Standard sensors are are available from many manufacturers with various accuracy specifications and numerous packaging options to suit most applications. Unlike thermocouples, it is not necessary to use special cables to connect to the sensor. 64 | 65 | For **LM-35** temperature sensor the output voltage is linearly proportional to the Celsius (Centigrade) temperature. LM35 does not require any external calibration or trimming to provide typical accuracies of ±1⁄4̊ C at room temperature and ±3⁄4̊C over a full −55 to +150 ̊C temperature range. Another temperature sensor PT100 is previously tested with ExpEYES. It offers excellent accuracy over a wide temperature range (from –200 to +850 °C). 66 | 67 | The LM35 series are precision integrated-circuit temperature sensors, whose output voltage is linearly proportional to the Celsius (Centigrade) temperature. The LM35 thus has an advantage over linear temperature sensors calibrated in ̊ Kelvin, as the user is not required to subtract a large constant voltage from its output to obtain convenient Centi- grade scaling. 68 | 69 | ####Hall Magnetic Sensor : Hall Sensor -3144 and Module KY-003 70 | 71 | Exploring the use of this magnetic sensor for measuring rotational speed of anemometer and other measurements was quiet interesting experience. Tried Hall sensor 3144 and KY-003 module. 72 | 73 | The KY-003 is a magnetic switch. If no magnetic field is present, the signal line of the sensor is HIGH (3.5 V). If a magnetic field is presented to the sensor, the signal line goes LOW, at the same time the LED on the sensor lights up. The polarity of the magnetic field is of influence to the switching action. The front side of the sensor needs the opposite polarity as the back of the sensor to switch on. 74 | 75 | 76 | ####Gas Sensors 77 | 78 | **Methane Gas Sensor MQ-4** This semiconductor gas sensor detects the presence of methane (CNG) gas at concentrations from 300 ppm to 10,000 ppm, a range suitable for detecting gas leaks. 79 | 80 | **LPG Gas Sensor MQ-6** This sensor detects the presence of LPG, isobutane, and propane at concentrations from 300 to 10,000 ppm. 81 | 82 | **Carbon Monoxide** Gas Sensor MQ-7 This gas sensor detects the presence of Carbon Monoxide at concentrations from 10 to 10,000 ppm. 83 | 84 | 85 | ####Piezielectric Transducer 86 | 87 | A piezoelectric sensor is a device that uses the piezoelectric effect, to measure changes in pressure, acceleration, temperature, strain, or force by converting them to an electrical charge. The prefix piezo- is Greek for 'press' or 'squeeze'. 88 | 89 | Cheap piezoceramic membrane used in piezoelectric ‘buzzers’ can be used as a very inexpensive, accurate and sensitive pressure sensor. These devices can be used both as sensors and actuators, so they’re referred to as transducers, a term applied to any device that can convert one form of energy to another. The sensor turns mechanical energy into electric potential, and the actuator converts electrical energy into mechanical force or motion. 90 | 91 | ### Barometric Pressure Sensor BMP 180 92 | 93 | BMP-180Tested BMP180 Digital Barometric Pressure Sensor Board Module :This precision sensor from Bosch is the best low-cost sensing solution for measuring barometric pressure and temperature. 94 | -------------------------------------------------------------------------------- /sensors/Temp-Humidity-Sensor/DHT11-raspberrypi.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import RPi.GPIO as GPIO 3 | import time 4 | 5 | def bin2dec(string_num): 6 | return str(int(string_num, 2)) 7 | 8 | data = [] 9 | 10 | GPIO.setmode(GPIO.BCM) 11 | 12 | GPIO.setup(4,GPIO.OUT) 13 | GPIO.output(4,GPIO.HIGH) 14 | time.sleep(0.025) 15 | GPIO.output(4,GPIO.LOW) 16 | time.sleep(0.02) 17 | 18 | GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_UP) 19 | 20 | for i in range(0,500): 21 | data.append(GPIO.input(4)) 22 | 23 | bit_count = 0 24 | tmp = 0 25 | count = 0 26 | HumidityBit = "" 27 | TemperatureBit = "" 28 | crc = "" 29 | 30 | try: 31 | while data[count] == 1: 32 | tmp = 1 33 | count = count + 1 34 | 35 | for i in range(0, 32): 36 | bit_count = 0 37 | 38 | while data[count] == 0: 39 | tmp = 1 40 | count = count + 1 41 | 42 | while data[count] == 1: 43 | bit_count = bit_count + 1 44 | count = count + 1 45 | 46 | if bit_count > 3: 47 | if i>=0 and i<8: 48 | HumidityBit = HumidityBit + "1" 49 | if i>=16 and i<24: 50 | TemperatureBit = TemperatureBit + "1" 51 | else: 52 | if i>=0 and i<8: 53 | HumidityBit = HumidityBit + "0" 54 | if i>=16 and i<24: 55 | TemperatureBit = TemperatureBit + "0" 56 | 57 | except: 58 | print ("ERR_RANGE") 59 | exit(0) 60 | 61 | try: 62 | for i in range(0, 8): 63 | bit_count = 0 64 | 65 | while data[count] == 0: 66 | tmp = 1 67 | count = count + 1 68 | 69 | while data[count] == 1: 70 | bit_count = bit_count + 1 71 | count = count + 1 72 | 73 | if bit_count > 3: 74 | crc = crc + "1" 75 | else: 76 | crc = crc + "0" 77 | except: 78 | print ("ERR_RANGE") 79 | exit(0) 80 | 81 | Humidity = bin2dec(HumidityBit) 82 | Temperature = bin2dec(TemperatureBit) 83 | 84 | if int(Humidity) + int(Temperature) - int(bin2dec(crc)) == 0: 85 | print ("Humidity:"+ Humidity +"%") 86 | print ("Temperature:"+ Temperature +"C") 87 | else: 88 | print ("ERR_CRC") 89 | -------------------------------------------------------------------------------- /sensors/Temp-Humidity-Sensor/DHT11.md: -------------------------------------------------------------------------------- 1 | 2 | ##DHT11 Temperature Humidity Sensor Module 3 | 4 | 5 | This Digital sensor module includes resistive humidity sensing component and NTC temperature testing. 6 | 7 | Specification: 8 | 9 | Signal transmission range: 20m 10 | Humidity measuring range: 20 - 95% RH 11 | Humidity measurement error: + / -5% 12 | Temperature measurement range: 0 - 50°C 13 | Temperature measurement error: + / -2°C 14 | Operating voltage: 3.3 - 5V 15 | 16 | The DHT11 is a basic, ultra low-cost digital temperature and humidity sensor. It uses a capacitive humidity sensor and a thermistor to measure the surrounding air, and spits out a digital signal on the data pin (no analog input pins needed). Its fairly simple to use, but requires careful timing to grab data. The only real downside of this sensor is you can only get new data from it once every 2 seconds. 17 | 18 | The DHT11 is chosen because it is lab calibrated, accurate and stable and its signal output is digital. Most important of all, it is relatively inexpensive for the given performance. Below is the pinout of the sensor. 19 | Datasheet 20 | 21 | 22 | Pin Name Description 23 | 1 VDD Power supply 3 - 5.5 V DC 24 | 2 DATA Serial data output 25 | 3 NC Not connected 26 | 4 GND Ground 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /sensors/Temp-Humidity-Sensor/reading-DHT11-trial.txt: -------------------------------------------------------------------------------- 1 | The DHT11 data sheet says that if we pull the input line LOW for 18 ms, 2 | pull the line HIGH and wait for 20-40 us, the DHT11 should start transmitting data. 3 | Pulling the line LOW can be done by just pressing the button. 4 | 5 | Here's the oscilloscope output right after I press the push button. 6 | 7 | Just like the data sheet said, 80 us LOW, 80 us HIGH, followed by 40 bits of data. 8 | The HIGH bits are 70 us long, and the LOW bits are 26-28 us long. 9 | Writing this bit stream out on a piece of paper... 10 | 11 | 00110111 00000000 00011010 00000000 01010001 12 | 13 | Let's decode this with a bit of Python: 14 | 15 | >>> x = '00110111 00000000 00011010 00000000 01010001'.split() 16 | >>> x 17 | ['00110111', '00000000', '00011010', '00000000', '01010001'] 18 | >>> [int(i, 2) for i in x] 19 | [55, 0, 26, 0, 81] 20 | >>> 21 | 22 | The first two numbers represent the Relative Humidity % (55.0), 23 | the next two the temperature n Centigrade (26.0), and the last number is a checksum (81 == 55 + 26). 24 | Looks good! 25 | -------------------------------------------------------------------------------- /sensors/Temperatur-Sensor/Temp-PT100-GUI.py: -------------------------------------------------------------------------------- 1 | ''' 2 | expEYES program for measuring temperature using PT100 sensor 3 | License : GNU GPL version 3 4 | ''' 5 | import gettext 6 | gettext.bindtextdomain("expeyes") 7 | gettext.textdomain('expeyes') 8 | _ = gettext.gettext 9 | 10 | import time, math, sys 11 | if sys.version_info.major==3: 12 | from tkinter import * 13 | else: 14 | from Tkinter import * 15 | 16 | sys.path=[".."] + sys.path 17 | 18 | import time, math, sys 19 | if sys.version_info.major==3: 20 | from tkinter import * 21 | else: 22 | from Tkinter import * 23 | 24 | sys.path=[".."] + sys.path 25 | 26 | import expeyes.eyesj as eyes 27 | import expeyes.eyeplot as eyeplot 28 | import expeyes.eyemath as eyemath 29 | 30 | WIDTH = 600 # width of drawing canvas 31 | HEIGHT = 400 # height 32 | 33 | class PT100: 34 | tv = [ [], [] ] # Lists for Readings 35 | TIMER = 500 # Time interval between reads 36 | MINY = 0 # Temperature range 37 | MAXY = 100 38 | running = False 39 | current = 1.0 # 1mA nominal 40 | gain = 1.0 41 | 42 | def v2t(self, v): # Convert Voltage to Temperature for PT100 43 | r = v / self.gain / (self.current * 1.0e-3) # mA to Ampere 44 | r0 = 100.0 45 | A = 3.9083e-3 46 | B = -5.7750e-7 47 | c = 1 - r/r0 48 | b4ac = math.sqrt( A*A - 4 * B * c) 49 | t = (-A + b4ac) / (2.0 * B) 50 | return t 51 | 52 | def xmgrace(self): 53 | if self.running == True: 54 | return 55 | p.grace([self.tv]) 56 | 57 | def start(self): 58 | self.running = True 59 | self.index = 0 60 | self.tv = [ [], [] ] 61 | try: 62 | self.MAXTIME = int(DURATION.get()) 63 | self.MINY = int(TMIN.get()) 64 | self.MAXY = int(TMAX.get()) 65 | self.gain = float(Gval.get()) 66 | self.current = float(CCval.get()) 67 | #print self.gain, self.current 68 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('Volt')) 69 | self.TIMER = int(TGAP.get()) 70 | Total.config(state=DISABLED) 71 | Dur.config(state=DISABLED) 72 | self.msg(_('Starting the Measurements')) 73 | root.after(self.TIMER, self.update) 74 | except: 75 | self.msg(_('Failed to Start')) 76 | 77 | def stop(self): 78 | self.running = False 79 | Total.config(state=NORMAL) 80 | Dur.config(state=NORMAL) 81 | self.msg(_('User Stopped the measurements')) 82 | 83 | def update(self): 84 | if self.running == False: 85 | return 86 | t,v = p.get_voltage_time(3) # Read A1 87 | if len(self.tv[0]) == 0: 88 | self.start_time = t 89 | elapsed = 0 90 | else: 91 | elapsed = t - self.start_time 92 | self.tv[0].append(elapsed) 93 | if self.calibrated: 94 | temp = self.m * v + self.c # Use the calibration 95 | else: 96 | temp = self.v2t(v) 97 | self.tv[1].append(temp) 98 | if len(self.tv[0]) >= 2: 99 | g.delete_lines() 100 | g.line(self.tv[0], self.tv[1]) 101 | if elapsed > self.MAXTIME: 102 | self.running = False 103 | Total.config(state=NORMAL) 104 | Dur.config(state=NORMAL) 105 | self.msg(_('Completed the Measurements')) 106 | return 107 | root.after(self.TIMER, self.update) 108 | 109 | def calc_gain(self): 110 | vs = p.set_voltage(.1) 111 | va = p.get_voltage(1) 112 | if va < -1: 113 | self.gain = va/vs 114 | else: 115 | self.gain = 1 116 | self.msg(_('Wrong connections or value of Rg'),'red') 117 | Gval.set('%5.1f'%(self.gain)) 118 | 119 | def save(self): 120 | try: 121 | fn = filename.get() 122 | except: 123 | fn = 'pt100.dat' 124 | p.save([self.tv],fn) 125 | self.msg(_('Data saved to %s')%fn) 126 | 127 | def clear(self): 128 | if self.running == True: 129 | return 130 | self.nt = [ [], [] ] 131 | g.delete_lines() 132 | self.msg(_('Cleared Data and Trace')) 133 | 134 | def msg(self,s, col = 'blue'): 135 | msgwin.config(text=s, fg=col) 136 | 137 | def quit(self): 138 | p.set_state(11,0) 139 | sys.exit() 140 | 141 | p = eyes.open() 142 | p.disable_actions() 143 | p.set_state(11,1) 144 | root = Tk() 145 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 146 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 147 | pt = PT100() 148 | 149 | cf = Frame(root, width = WIDTH, height = 10) 150 | cf.pack(side=TOP, fill = BOTH, expand = 1) 151 | 152 | b3 = Label(cf, text = _('Read Every')) 153 | b3.pack(side = LEFT, anchor = SW) 154 | TGAP = StringVar() 155 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 156 | TGAP.set('500') 157 | Dur.pack(side = LEFT, anchor = SW) 158 | b3 = Label(cf, text = _('mS,')) 159 | b3.pack(side = LEFT, anchor = SW) 160 | b3 = Label(cf, text = _('for total')) 161 | b3.pack(side = LEFT, anchor = SW) 162 | DURATION = StringVar() 163 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 164 | DURATION.set('100') 165 | Total.pack(side = LEFT, anchor = SW) 166 | b3 = Label(cf, text = _('Seconds.')) 167 | b3.pack(side = LEFT, anchor = SW) 168 | 169 | b3 = Label(cf, text = _('Range')) 170 | b3.pack(side = LEFT, anchor = SW) 171 | TMIN = StringVar() 172 | TMIN.set('0') 173 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 174 | Tmin.pack(side = LEFT, anchor = SW) 175 | b3 = Label(cf, text = _('to,')) 176 | b3.pack(side = LEFT, anchor = SW) 177 | TMAX = StringVar() 178 | TMAX.set('200') 179 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 180 | Tmax.pack(side = LEFT, anchor = SW) 181 | b3 = Label(cf, text = _('C. ')) 182 | b3.pack(side = LEFT, anchor = SW) 183 | b1 = Button(cf, text = _('START'), command = pt.start) 184 | b1.pack(side = LEFT, anchor = N) 185 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 186 | b1.pack(side = LEFT, anchor = N) 187 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 188 | b4.pack(side = LEFT, anchor = N) 189 | 190 | cf = Frame(root, width = WIDTH, height = 10) 191 | cf.pack(side=TOP, fill = BOTH, expand = 1) 192 | 193 | 194 | b3 = Label(cf, text = _('Current =')) 195 | b3.pack(side = LEFT, anchor = SW) 196 | CCval = StringVar() 197 | CCval.set('1.0') 198 | Ccs =Entry(cf, width=4, bg = 'white', textvariable = CCval) 199 | Ccs.pack(side = LEFT, anchor = SW) 200 | Label(cf, text = _('mA')).pack(side = LEFT, anchor = SW) 201 | b1 = Button(cf, text = _('Xmgrace'), command = pt.xmgrace) 202 | b1.pack(side = LEFT, anchor = N) 203 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 204 | b3.pack(side = LEFT, anchor = N) 205 | filename = StringVar() 206 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 207 | filename.set('temperature.dat') 208 | 209 | cf = Frame(root, width = WIDTH, height = 10) 210 | cf.pack(side=TOP, fill = BOTH, expand = 1) 211 | 212 | e1.pack(side = LEFT) 213 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 214 | b5.pack(side = RIGHT, anchor = N) 215 | 216 | mf = Frame(root, width = WIDTH, height = 10) 217 | mf.pack(side=TOP) 218 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 219 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 220 | 221 | root.title(_('Temperature Measuements using PT100')) 222 | root.mainloop() 223 | -------------------------------------------------------------------------------- /sensors/Temperatur-Sensor/about-LM35.md: -------------------------------------------------------------------------------- 1 | 2 | # Temperature Sensor LM-35 3 | 4 | The LM35 series are precision integrated-circuit temperature 5 | sensors, whose output voltage is linearly proportional to the 6 | Celsius (Centigrade) temperature. The LM35 thus has an 7 | advantage over linear temperature sensors calibrated in 8 | ̊ Kelvin, as the user is not required to subtract a large 9 | constant voltage from its output to obtain convenient Centi- 10 | grade scaling. The LM35 does not require any external 11 | calibration or trimming to provide typical accuracies of 12 | ±1⁄4̊ Cat room temperature and ±3⁄4̊C over a full −55 to +150 ̊C 13 | temperature range. Low cost is assured by trimming and 14 | calibration at the wafer level. The LM35’s low output imped- 15 | ance, linear output, and precise inherent calibration make 16 | interfacing to readout or control circuitry especially easy. It 17 | can be used with single power supplies, or with plus and 18 | minus supplies. As it draws only 60 μA from its supply, it has 19 | very low self-heating, less than 0.1 ̊C in still air. The LM35 is 20 | rated to operate over a −55 ̊ to +150 ̊C temperature range, 21 | while the LM35C is rated for a −40 ̊ to +110 ̊C range (−10 ̊ 22 | with improved accuracy). The LM35 series is available pack- 23 | aged in hermetic TO-46 transistor packages, while the 24 | LM35C, LM35CA, and LM35D are also available in the 25 | plastic TO-92 transistor package. The LM35D is also avail- 26 | able in an 8-lead surface mount small outline package and a 27 | plastic TO-220 package 28 | 29 | Source: http://www2.ece.ohio-state.edu/~passino/LM35.pdf 30 | -------------------------------------------------------------------------------- /sensors/Temperatur-Sensor/about-PT100.md: -------------------------------------------------------------------------------- 1 | ## PT100 platinum resistance thermometers 2 | 3 | Platinum resistance thermometers (PRTs) offer excellent accuracy over a wide temperature range (from –200 to +850 °C). Standard sensors are are available from many manufacturers with various accuracy specifications and numerous packaging options to suit most applications. Unlike thermocouples, it is not necessary to use special cables to connect to the sensor. 4 | 5 | The principle of operation is to measure the resistance of a platinum element. The most common type (PT100) has a resistance of 100 ohms at 0 °C and 138.4 ohms at 100 °C. There are also PT1000 sensors that have a resistance of 1000 ohms at 0 °C. 6 | 7 | The relationship between temperature and resistance is approximately linear over a small temperature range: for example, if you assume that it is linear over the 0 to 100 °C range, the error at 50 °C is 0.4 °C. For precision measurement, it is necessary to linearise the resistance to give an accurate temperature. The most recent definition of the relationship between resistance and temperature is International Temperature Standard 90 (ITS-90). 8 | 9 | The linearization equation is: 10 | 11 | Rt = R0 * (1 + A* t + B*t2 + C*(t-100)* t3) 12 | 13 | Where: 14 | 15 | Rt is the resistance at temperature t, R0 is the resistance at 0 °C, and 16 | A= 3.9083 E–3 17 | B = –5.775 E–7 18 | C = –4.183 E–12 (below 0 °C), or 19 | C = 0 (above 0 °C) 20 | 21 | For a PT100 sensor, a 1 °C temperature change will cause a 0.384 ohm change in resistance, so even a small error in measurement of the resistance (for example, the resistance of the wires leading to the sensor) can cause a large error in the measurement of the temperature. For precision work, sensors have four wires- two to carry the sense current, and two to measure the voltage across the sensor element. It is also possible to obtain three-wire sensors, although these operate on the (not necessarily valid) assumption that the resistance of each of the three wires is the same. 22 | -------------------------------------------------------------------------------- /sensors/Temperatur-Sensor/temp-LM35-GUI.py: -------------------------------------------------------------------------------- 1 | ''' 2 | GUI for Temperature Measurement using LM35 sensor 3 | 4 | 5 | ExpEYES program developed as a part of GSoC-2015 project 6 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 7 | 8 | Mentor Organization:FOSSASIA 9 | Mentors: Hong Phuc, Mario Behling, Rebentisch 10 | Author: Praveen Patil 11 | License : GNU GPL version 3 12 | 13 | ''' 14 | 15 | #connections LM35: Pin1 (v-in) to OD1, Pin 2 (OUT) to IN2 and Pin 3 to GND 16 | 17 | import gettext 18 | gettext.bindtextdomain("expeyes") 19 | gettext.textdomain('expeyes') 20 | _ = gettext.gettext 21 | 22 | import time, math, sys 23 | if sys.version_info.major==3: 24 | from tkinter import * 25 | else: 26 | from Tkinter import * 27 | 28 | sys.path=[".."] + sys.path 29 | 30 | 31 | import expeyes.eyesj as eyes 32 | import expeyes.eyeplot as eyeplot 33 | import expeyes.eyemath as eyemath 34 | 35 | WIDTH = 600 # width of drawing canvas 36 | HEIGHT = 400 # height 37 | 38 | class LM35: 39 | tv = [ [], [], [] ] # Lists for Readings 40 | TIMER = 1000 # Time interval between reads 41 | MINY = 0 # Temperature range 42 | MAXY = 100 43 | running = False 44 | 45 | 46 | def v2t(self, v): # Convert Voltage to Temperature for LM35 47 | 48 | t = v * 100 49 | return t 50 | 51 | def xmgrace(self): 52 | if self.running == True: 53 | return 54 | p.grace([self.tv]) 55 | 56 | def start(self): 57 | self.running = True 58 | self.index = 0 59 | self.tv = [ [], [], [] ] 60 | p.set_state (10,1) 61 | try: 62 | self.MAXTIME = int(DURATION.get()) 63 | self.MINY = int(TMIN.get()) 64 | self.MAXY = int(TMAX.get()) 65 | 66 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time in second'),_('Temp in celsius')) 67 | self.TIMER = int(TGAP.get()) 68 | Total.config(state=DISABLED) 69 | Dur.config(state=DISABLED) 70 | self.msg(_('Starting the Measurements')) 71 | root.after(self.TIMER, self.update) 72 | except: 73 | self.msg(_('Failed to Start')) 74 | 75 | def stop(self): 76 | self.running = False 77 | Total.config(state=NORMAL) 78 | Dur.config(state=NORMAL) 79 | self.msg(_('User Stopped the measurements')) 80 | 81 | def update(self): 82 | if self.running == False: 83 | return 84 | t,v = p.get_voltage_time(4) # Read IN2 as IN1 is researved for humidity sensor for capacity measurement 85 | if len(self.tv[0]) == 0: 86 | self.start_time = t 87 | elapsed = 0 88 | else: 89 | elapsed = t - self.start_time 90 | self.tv[0].append(elapsed) 91 | 92 | temp = self.v2t(v) 93 | self.tv[1].append(temp) 94 | fahrenheit= (9/5 * temp )+ 32 95 | self.tv[2].append(fahrenheit) 96 | if len(self.tv[0]) >= 2: 97 | g.delete_lines() 98 | 99 | g.line(self.tv[0], self.tv[1],1) # red line - temperature in celsius scale 100 | g.line(self.tv[0], self.tv[2],2) # blue line - temperature in fahrenheit scale 101 | if elapsed > self.MAXTIME: 102 | self.running = False 103 | Total.config(state=NORMAL) 104 | Dur.config(state=NORMAL) 105 | self.msg(_('Completed the Measurements')) 106 | return 107 | root.after(self.TIMER, self.update) 108 | 109 | 110 | def save(self): 111 | try: 112 | fn = filename.get() 113 | except: 114 | fn = 'LM35.dat' 115 | p.save([self.tv],fn) 116 | self.msg(_('Data saved to %s')%fn) 117 | 118 | def clear(self): 119 | if self.running == True: 120 | return 121 | self.nt = [ [], [] ] 122 | g.delete_lines() 123 | self.msg(_('Cleared Data and Trace')) 124 | 125 | def msg(self,s, col = 'blue'): 126 | msgwin.config(text=s, fg=col) 127 | 128 | def quit(self): 129 | p.set_state(10,0) 130 | sys.exit() 131 | 132 | p = eyes.open() 133 | p.disable_actions() 134 | 135 | root = Tk() 136 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) 137 | 138 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) 139 | pt = LM35() 140 | 141 | cf = Frame(root, width = WIDTH, height = 10) 142 | cf.pack(side=TOP, fill = BOTH, expand = 1) 143 | 144 | b3 = Label(cf, text = _('Read Every')) 145 | b3.pack(side = LEFT, anchor = SW) 146 | TGAP = StringVar() 147 | Dur =Entry(cf, width=5, bg = 'white', textvariable = TGAP) 148 | TGAP.set('1000') 149 | Dur.pack(side = LEFT, anchor = SW) 150 | b3 = Label(cf, text = _('mS,')) 151 | b3.pack(side = LEFT, anchor = SW) 152 | b3 = Label(cf, text = _('for total')) 153 | b3.pack(side = LEFT, anchor = SW) 154 | DURATION = StringVar() 155 | Total =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 156 | DURATION.set('100') 157 | Total.pack(side = LEFT, anchor = SW) 158 | b3 = Label(cf, text = _('Seconds.')) 159 | b3.pack(side = LEFT, anchor = SW) 160 | 161 | b3 = Label(cf, text = _('Range')) 162 | b3.pack(side = LEFT, anchor = SW) 163 | TMIN = StringVar() 164 | TMIN.set('0') 165 | Tmin =Entry(cf, width=5, bg = 'white', textvariable = TMIN) 166 | Tmin.pack(side = LEFT, anchor = SW) 167 | b3 = Label(cf, text = _('to,')) 168 | b3.pack(side = LEFT, anchor = SW) 169 | TMAX = StringVar() 170 | TMAX.set('100') 171 | Tmax =Entry(cf, width=5, bg = 'white', textvariable = TMAX) 172 | Tmax.pack(side = LEFT, anchor = SW) 173 | b3 = Label(cf, text = _('C. ')) 174 | 175 | b3 = Button(cf, text = _('SAVE to'), command = pt.save) 176 | b3.pack(side = LEFT, anchor = SW) 177 | b3.pack(side = LEFT, anchor = SW) 178 | filename = StringVar() 179 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 180 | filename.set('temperature.dat') 181 | e1.pack(side = LEFT, anchor = SW) 182 | 183 | cf = Frame(root, width = WIDTH, height = 10) 184 | cf.pack(side=TOP, fill = BOTH, expand = 1) 185 | 186 | b1 = Button(cf, text = _('Xmgrace'), command = pt.xmgrace) 187 | b1.pack(side = LEFT, anchor = SW) 188 | 189 | 190 | cf = Frame(root, width = WIDTH, height = 10) 191 | cf.pack(side=TOP, fill = BOTH, expand = 1) 192 | e1.pack(side = LEFT) 193 | 194 | b3 = Label(cf, text = _(' RED Line - Temperature in Celsius'), fg = 'red') 195 | b3.pack(side = LEFT, anchor = SW) 196 | b3 = Label(cf, text = _(' BLUE Line - Temperature in Fahrenheit'), fg = 'blue') 197 | b3.pack(side = LEFT, anchor = SW) 198 | 199 | b5 = Button(cf, text = _('QUIT'), command = pt.quit) 200 | b5.pack(side = RIGHT, anchor = N) 201 | b4 = Button(cf, text = _('CLEAR'), command = pt.clear) 202 | b4.pack(side = RIGHT, anchor = N) 203 | b1 = Button(cf, text = _('STOP'), command = pt.stop) 204 | b1.pack(side = RIGHT, anchor = N) 205 | b1 = Button(cf, text = _('START'), command = pt.start) 206 | b1.pack(side = RIGHT, anchor = N) 207 | 208 | mf = Frame(root, width = WIDTH, height = 10) 209 | mf.pack(side=TOP) 210 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 211 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 212 | 213 | root.title(_('Temperature Measuements using LM35')) 214 | root.mainloop() 215 | -------------------------------------------------------------------------------- /sensors/Test-Programs/Anemometer-Speed-Photogate.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | ''' 3 | Connect photogate with LED between OD1 and GND and PhotoDiode between IN1 and GND 4 | 5 | Use function print p.get_frequency(3) # to get frequency of square wave at at pin 3 6 | ''' 7 | 8 | import expeyes.eyemath as em 9 | import expeyes.eyesj as ej 10 | 11 | p = ej.open() 12 | p.set_state(10,1) # sets OD1 at HIGH, Channel No for OD1 id 10 13 | print (p.get_frequency(3)) # function to measure frequency 14 | # magnetic sensor can also be used for this purpose 15 | 16 | -------------------------------------------------------------------------------- /sensors/Test-Programs/Anemometer-Speed-magneticpickup.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | ''' 4 | Connect pickup coil to A1 and Fit the sine wave for getting frequency. 5 | From frequency of rotation of anemometer wind speed can be calculated 6 | ''' 7 | import gettext 8 | gettext.bindtextdomain("expeyes") 9 | gettext.textdomain('expeyes') 10 | _ = gettext.gettext 11 | 12 | import expeyes.eyesj as ej 13 | import expeyes.eyemath as em 14 | from pylab import plot, show 15 | 16 | p = ej.open() 17 | t,v= p.capture(1,400,100) 18 | try: 19 | vfit, par = em.fit_sine(t,v) 20 | print (par[1]) # second parameter is frequency 21 | print((t,v)) 22 | plot(t, vfit) 23 | show() 24 | except: 25 | print("No alternative signal, please make another try.") 26 | 27 | -------------------------------------------------------------------------------- /sensors/Ultrasonic-Motion-Sensor/Getecho.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | ''' ExpEYES program to get echo from SRF-05/SRF-04 ultrasonic senso, measure echo time and calculate distance 3 | ''' 4 | import gettext 5 | gettext.bindtextdomain("expeyes") 6 | gettext.textdomain('expeyes') 7 | _ = gettext.gettext 8 | 9 | 10 | 11 | import time, sys, math 12 | if sys.version_info.major==3: 13 | from tkinter import * 14 | else: 15 | from Tkinter import * 16 | sys.path=[".."] + sys.path 17 | import expeyes.eyesj as eyes 18 | import expeyes.eyeplot as eyeplot 19 | import expeyes.eyemath as eyemath 20 | 21 | import expeyes.eyesj as ej 22 | 23 | p=ej.open() 24 | if p == None: sys.exit() 25 | p.set_state(10,1) 26 | 27 | TIMER = 100 28 | WIDTH = 200 29 | HEIGHT = 500 30 | X = WIDTH/2 31 | vs = 0.034000 32 | 33 | def action(): 34 | global pos, txt,strt 35 | t = p.srfechotime(9,0) 36 | if t > 10000: 37 | p.set_sqr1(-1) 38 | w.after(20,action) 39 | return 40 | s = (t-400) *vs/2 41 | ss = 'Reflector at %5.1f cm'%s 42 | print (time.time()-strt, s) 43 | y = HEIGHT - s*10 44 | c.delete(pos) 45 | c.delete(txt) 46 | pos = c.create_rectangle([X,y,X+20, y + 5], outline='red') 47 | txt = c.create_text(X,20,text=ss) 48 | p.set_sqr1(t) 49 | w.after(TIMER,action) 50 | 51 | w = Tk() 52 | c = Canvas(w, width=WIDTH, height=HEIGHT) 53 | c.pack() 54 | pos = c.create_rectangle([X,0,X+20, 5], outline='red') 55 | txt = c.create_text(X,50,text='') 56 | w.after(0,action) 57 | strt = time.time() 58 | w.mainloop() 59 | -------------------------------------------------------------------------------- /sensors/Ultrasonic-Motion-Sensor/Motion-Sensor-GUI.py: -------------------------------------------------------------------------------- 1 | ''' 2 | ExpEYES program for Ultrasonic Motion Sensor SRF-o5 3 | 4 | Authors: Praveen Patil, Dr. Ajith Kumar 5 | 6 | Developed as a part of GSoC Project 7 | Mentor Organization: FOSSASIA www.fossasia.org 8 | Mentors: Mario Behling, Hong Phuc 9 | License : GNU GPL version 3 10 | 11 | This program allows user to ultrasonic motion sensors (SRF-05 module) and plot both the graphs 12 | in real-time. 13 | 14 | Connect gnd to ground, echo to sen, trig to sqr2 and od1 to vcc of SRF-05 15 | ''' 16 | 17 | import gettext 18 | gettext.bindtextdomain("expeyes") 19 | gettext.textdomain('expeyes') 20 | _ = gettext.gettext 21 | 22 | import time, math, sys 23 | if sys.version_info.major==3: 24 | from tkinter import * #support for python 3 25 | else: 26 | from Tkinter import * 27 | 28 | sys.path=[".."] + sys.path 29 | 30 | import expeyes.eyesj as eyes 31 | import expeyes.eyeplot as eyeplot 32 | import expeyes.eyemath as eyemath 33 | 34 | #from Tkinter import * 35 | #import expeyes.eyesj as eyes, expeyes.eyeplot as eyeplot, time, sys, math 36 | 37 | WIDTH = 800 # width of drawing canvas 38 | HEIGHT = 400 # height 39 | vs = 0.034000 40 | 41 | class Motion: 42 | tv = [ [], [], [] ] # Lists for Readings 43 | TIMER = 10 # Time interval between reads 44 | MINY = 0 45 | MAXY = 80 46 | running = False 47 | MAXTIME = 10 48 | 49 | def xmgrace(self): 50 | if self.running == True: 51 | return 52 | p.grace([self.tv]) 53 | 54 | def start(self): 55 | self.running = True 56 | self.index = 0 57 | self.tv = [ [], []] 58 | try: 59 | self.MAXTIME = int(DURATION.get()) 60 | self.MAXY = int(MAXDIST.get()) 61 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('cm')) 62 | Dur.config(state=DISABLED) 63 | self.msg(_('Starting the Measurements')) 64 | root.after(self.TIMER, self.update) 65 | except: 66 | self.msg(_('Failed to Start')) 67 | 68 | def stop(self): 69 | self.running = False 70 | Dur.config(state=NORMAL) 71 | self.msg(_('User Stopped the measurements')) 72 | 73 | def update(self): 74 | if self.running == False: 75 | return 76 | tt = p.srfechotime(9,0) 77 | dist = (tt-400) *vs/2 78 | 79 | if len(self.tv[0]) == 0: 80 | self.start_time = time.time() 81 | elapsed = 0 82 | else: 83 | elapsed = time.time() - self.start_time 84 | self.tv[0].append(elapsed) 85 | self.tv[1].append(dist) 86 | 87 | if len(self.tv[0]) >= 2: 88 | g.delete_lines() 89 | g.line(self.tv[0], self.tv[1]) 90 | 91 | if elapsed > self.MAXTIME: 92 | self.running = False 93 | Dur.config(state=NORMAL) 94 | self.msg(_('Completed the Measurements')) 95 | return 96 | root.after(self.TIMER, self.update) 97 | 98 | def save(self): 99 | try: 100 | fn = filename.get() 101 | except: 102 | fn = 'motion2.dat' 103 | p.save([self.tv],fn) 104 | self.msg(_('Data saved to %s')%fn) 105 | 106 | def clear(self): 107 | if self.running == True: 108 | return 109 | self.tv = [ [], [] ] 110 | g.delete_lines() 111 | self.msg(_('Cleared Data and Trace')) 112 | 113 | def msg(self,s, col = 'blue'): 114 | msgwin.config(text=s, fg=col) 115 | 116 | p = eyes.open() 117 | p.disable_actions() 118 | p.set_state(10,1) # makes OD1 High 119 | root = Tk() 120 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 121 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) # make plot objects using draw.disp 122 | pen = Motion() 123 | 124 | cf = Frame(root, width = WIDTH, height = 10) 125 | cf.pack(side=TOP, fill = BOTH, expand = 1) 126 | 127 | 128 | b3 = Label(cf, text = _('Digitize for')) 129 | b3.pack(side = LEFT, anchor = SW) 130 | DURATION = StringVar() 131 | Dur =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 132 | DURATION.set('10') 133 | Dur.pack(side = LEFT, anchor = SW) 134 | b3 = Label(cf, text = _('Seconds.')) 135 | b3.pack(side = LEFT, anchor = SW) 136 | b3 = Label(cf, text = _('Max Dist=')) 137 | b3.pack(side = LEFT, anchor = SW) 138 | MAXDIST = StringVar() 139 | Dis =Entry(cf, width=5, bg = 'white', textvariable = MAXDIST) 140 | MAXDIST.set('60') 141 | Dis.pack(side = LEFT, anchor = SW) 142 | b3 = Label(cf, text = _('cm')) 143 | b3.pack(side = LEFT, anchor = SW) 144 | 145 | cf = Frame(root, width = WIDTH, height = 10) 146 | cf.pack(side=TOP, fill = BOTH, expand = 1) 147 | b1 = Button(cf, text = _('START'), command = pen.start) 148 | b1.pack(side = LEFT, anchor = N) 149 | b1 = Button(cf, text = _('STOP'), command = pen.stop) 150 | b1.pack(side = LEFT, anchor = N) 151 | b4 = Button(cf, text = _('CLEAR'), command = pen.clear) 152 | b4.pack(side = LEFT, anchor = N) 153 | b1 = Button(cf, text = _('Xmgrace'), command = pen.xmgrace) 154 | b1.pack(side = LEFT, anchor = N) 155 | b3 = Button(cf, text = _('SAVE to'), command = pen.save) 156 | b3.pack(side = LEFT, anchor = N) 157 | filename = StringVar() 158 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 159 | filename.set('motion2.dat') 160 | e1.pack(side = LEFT) 161 | b5 = Button(cf, text = _('QUIT'), command = sys.exit) 162 | b5.pack(side = RIGHT, anchor = N) 163 | 164 | mf = Frame(root, width = WIDTH, height = 10) 165 | mf.pack(side=TOP) 166 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 167 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 168 | 169 | 170 | #eyeplot.pop_image('pics/imagename.png', _('write the name of expt setup image')) 171 | root.title(_('Motion Graph using Position Sensor SRF-05')) 172 | root.mainloop() 173 | -------------------------------------------------------------------------------- /sensors/Ultrasonic-Motion-Sensor/Motion-Sensor-SRF-05.md: -------------------------------------------------------------------------------- 1 | ##HY-SRF05 Ultrasonic Position Sensor 2 | Ultrasonic sensors overcome many of the weaknesses of IR sensors - they provide distance measurement regardless of color and lighting of obstacles. They also provide lower minimum distances and wider angles of detection to gaurantee that obstacles are not missed by a narrow sensor beam. 3 | 4 | 5 | The SRF05 has been designed to increase flexibility, increase range, and to reduce costs still further. As such, the SRF05 is fully compatible with the SRF04. Range is increased from 3 meters to 4 meters. A new operating mode (tying the mode pin to ground) allows the SRF05 to use a single pin for both trigger and echo, thereby saving valuable pins on your controller. When the mode pin is left unconnected, the SRF05 operates with separate trigger and echo pins, like the SRF04. The SRF05 includes a small delay before the echo pulse to give slower controllers such as the Basic Stamp and Picaxe time to execute their pulse in commands. 6 | 7 | ###Specifications 8 | 5-Pin, One each for VCC, Trigger, Echo, Out and Ground. 9 | 10 | 11 | 1. Voltage : DC5V 12 | 2. Static current : less than 2mA 13 | 3. Detection distance: 2cm-450cm 14 | 4. High precision: up to 0.3c 15 | 16 | The module performance is stable, measure the distance accurately: 17 | Main technical parameters: 18 | 1) Voltage : DC5V 19 | 2) Static current : less than 2mA 20 | 3) level output: high-5V 21 | 4) level output: the end of 0V 22 | 5) Sensor angle: not more than 15 degrees 23 | 6) Detection distance: 2cm-450cm 24 | 7) High precision: up to 0.3cm 25 | -------------------------------------------------------------------------------- /sensors/Ultrasonic-Motion-Sensor/motion-srf-two-sensors.py: -------------------------------------------------------------------------------- 1 | ''' 2 | ExpEYES program developed as a part of GSoC-2015 project 3 | (Modified from the program developed for GSoC-14) 4 | 5 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 6 | Mentor Organization:FOSSASIA 7 | Mentors: Hong Phuc, Mario Behling, Rebentisch 8 | Author: Praveen Patil 9 | License : GNU GPL version 3 10 | 11 | this program allows user to use TWO motion sensors (srf-05 modules) and plot both the graphs 12 | in real-time. 13 | This can be used for studying collisions, conservation of momentum etc... 14 | ''' 15 | 16 | import gettext 17 | gettext.bindtextdomain("expeyes") 18 | gettext.textdomain('expeyes') 19 | _ = gettext.gettext 20 | 21 | import sys 22 | if sys.version_info.major==3: 23 | from tkinter import * 24 | else: 25 | from Tkinter import * 26 | import expeyes.eyesj as eyes, expeyes.eyeplot as eyeplot, time, sys, math 27 | 28 | WIDTH = 600 # width of drawing canvas 29 | HEIGHT = 400 # height 30 | vs = 0.034000 31 | 32 | class SRF2: 33 | tv = [ [], [], [] ] # Lists for Readings 34 | TIMER = 10 # Time interval between reads 35 | MINY = 0 36 | MAXY = 80 37 | running = False 38 | MAXTIME = 10 39 | 40 | def xmgrace(self): 41 | if self.running == True: 42 | return 43 | p.grace([self.tv]) 44 | 45 | def start(self): 46 | self.running = True 47 | self.index = 0 48 | self.tv = [ [], [], [] ] 49 | try: 50 | self.MAXTIME = int(DURATION.get()) 51 | self.MAXY = int(MAXDIST.get()) 52 | g.setWorld(0, self.MINY, self.MAXTIME, self.MAXY,_('Time'),_('cm')) 53 | Dur.config(state=DISABLED) 54 | self.msg(_('Starting the Measurements')) 55 | root.after(self.TIMER, self.update) 56 | except: 57 | self.msg(_('Failed to Start')) 58 | 59 | def stop(self): 60 | self.running = False 61 | Dur.config(state=NORMAL) 62 | self.msg(_('User Stopped the measurements')) 63 | 64 | def update(self): 65 | if self.running == False: 66 | return 67 | tt = p.srfechotime(9,0) 68 | dist = (tt-400) *vs/2 69 | tt2 = p.srfechotime(8,3) 70 | dist2 = (tt2-400) *vs/2 71 | if len(self.tv[0]) == 0: 72 | self.start_time = time.time() 73 | elapsed = 0 74 | else: 75 | elapsed = time.time() - self.start_time 76 | self.tv[0].append(elapsed) 77 | self.tv[1].append(dist) 78 | self.tv[2].append(dist2) 79 | if len(self.tv[0]) >= 2: 80 | g.delete_lines() 81 | g.line(self.tv[0], self.tv[1]) 82 | g.line(self.tv[0], self.tv[2],1) 83 | if elapsed > self.MAXTIME: 84 | self.running = False 85 | Dur.config(state=NORMAL) 86 | self.msg(_('Completed the Measurements')) 87 | return 88 | root.after(self.TIMER, self.update) 89 | 90 | def save(self): 91 | try: 92 | fn = filename.get() 93 | except: 94 | fn = 'motion2.dat' 95 | p.save([self.tv],fn) 96 | self.msg(_('Data saved to %s')%fn) 97 | 98 | def clear(self): 99 | if self.running == True: 100 | return 101 | self.tv = [ [], [] ] 102 | g.delete_lines() 103 | self.msg(_('Cleared Data and Trace')) 104 | 105 | def msg(self,s, col = 'blue'): 106 | msgwin.config(text=s, fg=col) 107 | 108 | p = eyes.open() 109 | p.disable_actions() 110 | root = Tk() 111 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 112 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT, bip=False) # make plot objects using draw.disp 113 | pen = SRF2() 114 | 115 | cf = Frame(root, width = WIDTH, height = 10) 116 | cf.pack(side=TOP, fill = BOTH, expand = 1) 117 | 118 | 119 | b3 = Label(cf, text = _('Digitize for')) 120 | b3.pack(side = LEFT, anchor = SW) 121 | DURATION = StringVar() 122 | Dur =Entry(cf, width=5, bg = 'white', textvariable = DURATION) 123 | DURATION.set('10') 124 | Dur.pack(side = LEFT, anchor = SW) 125 | b3 = Label(cf, text = _('Seconds.')) 126 | b3.pack(side = LEFT, anchor = SW) 127 | b3 = Label(cf, text = _('Max Dist=')) 128 | b3.pack(side = LEFT, anchor = SW) 129 | MAXDIST = StringVar() 130 | Dis =Entry(cf, width=5, bg = 'white', textvariable = MAXDIST) 131 | MAXDIST.set('60') 132 | Dis.pack(side = LEFT, anchor = SW) 133 | b3 = Label(cf, text = _('cm')) 134 | b3.pack(side = LEFT, anchor = SW) 135 | 136 | cf = Frame(root, width = WIDTH, height = 10) 137 | cf.pack(side=TOP, fill = BOTH, expand = 1) 138 | b1 = Button(cf, text = _('START'), command = pen.start) 139 | b1.pack(side = LEFT, anchor = N) 140 | b1 = Button(cf, text = _('STOP'), command = pen.stop) 141 | b1.pack(side = LEFT, anchor = N) 142 | b4 = Button(cf, text = _('CLEAR'), command = pen.clear) 143 | b4.pack(side = LEFT, anchor = N) 144 | b1 = Button(cf, text = _('Xmgrace'), command = pen.xmgrace) 145 | b1.pack(side = LEFT, anchor = N) 146 | b3 = Button(cf, text = _('SAVE to'), command = pen.save) 147 | b3.pack(side = LEFT, anchor = N) 148 | filename = StringVar() 149 | e1 =Entry(cf, width=15, bg = 'white', textvariable = filename) 150 | filename.set('motion2.dat') 151 | e1.pack(side = LEFT) 152 | b5 = Button(cf, text = _('QUIT'), command = sys.exit) 153 | b5.pack(side = RIGHT, anchor = N) 154 | 155 | mf = Frame(root, width = WIDTH, height = 10) 156 | mf.pack(side=TOP) 157 | msgwin = Label(mf,text=_('Message'), fg = 'blue') 158 | msgwin.pack(side=LEFT, anchor = S, fill=BOTH, expand=1) 159 | 160 | 161 | #eyeplot.pop_image('pics/imagename.png', _('write the name of expt setup image')) 162 | root.title(_('Motion Graphs Using Two Position Sensors')) 163 | root.mainloop() 164 | -------------------------------------------------------------------------------- /sensors/Ultrasonic-Motion-Sensor/velocityofsound.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Program for measuring velocity of sound using ExpEYES 3 | License : GNU GPL 4 | ''' 5 | import gettext 6 | gettext.bindtextdomain("expeyes") 7 | gettext.textdomain('expeyes') 8 | _ = gettext.gettext 9 | 10 | import sys 11 | if sys.version_info.major==3: 12 | from tkinter import * 13 | else: 14 | from Tkinter import * 15 | 16 | import expeyes.eyes as eyes, expeyes.eyeplot as eyeplot, expeyes.eyemath as eyemath, time, sys, math 17 | 18 | TIMER = 100 19 | WIDTH = 800 # width of drawing canvas 20 | HEIGHT = 400 # height 21 | delay = 10 # Time interval between samples 22 | NP = 200 # Number of samples 23 | data = [] # Of the form, [ [x1,y1], [x2,y2],....] where x and y are vectors 24 | outmask = 1 25 | looping = False 26 | 27 | def fset(f): 28 | s = '%5.1f'%f 29 | Freq.delete(0,END) 30 | Freq.insert(0,s) 31 | 32 | def update(): 33 | global data, looping, NP, delay 34 | data = [] 35 | if looping == False: 36 | return 37 | t,v,tt,vv = p.capture01(NP,delay) 38 | for k in range(len(vv)): vv[k] -= 2.5 39 | g.delete_lines() 40 | g.line(t,v) 41 | g.line(tt,vv,1) 42 | data.append([t,v]) 43 | data.append([tt,vv]) 44 | fa = eyemath.fit_sine(t, v) 45 | if fa != None: 46 | #g.line(t,fa[0], 8) 47 | rms = p.rms(v) 48 | f0 = fa[1][1] * 1000 49 | s = _('Phase = %5.0f deg')%(fa[1][2]*180/math.pi) 50 | else: 51 | s = _('No Signal') 52 | msgwin.config(text=s) # CRO part over 53 | root.after(TIMER, update) 54 | 55 | 56 | def start(): 57 | global looping, NP, delay 58 | if A1.get() == 1: 59 | p.set_upv(5) 60 | f1 = float(Freq.get()) 61 | fr = p.set_sqr1(f1) 62 | fset(fr) 63 | looping = True 64 | p.adc2cmp(7) 65 | p.enable_wait_rising(4) 66 | root.after(TIMER, update) 67 | else: 68 | looping = False 69 | p.set_sqr1(0) 70 | 71 | def do_fft(): 72 | global data, delay, NP 73 | if data == []: return 74 | fr,tr = eyemath.fft(data[0][1], delay * 0.001) 75 | p.save([ [fr,tr] ], 'FFT.dat') 76 | p.grace([ [fr,tr] ], _('freq'), _('power')) 77 | msgwin.config(text = _('Fourier transform Saved to FFT.dat.')) 78 | 79 | def save(): 80 | global data 81 | s = fn.get() 82 | if s == '': 83 | return 84 | p.save(data, s) 85 | msgwin.config(text = _('Data saved to file ')+s) 86 | 87 | def xmgrace(): # Send the data to Xmgrace 88 | global data 89 | p.grace(data, _('milliSeconds'), _('Volts')) 90 | 91 | def quit(): 92 | p.write_outputs(0) 93 | sys.exit() 94 | 95 | p = eyes.open() 96 | p.loadall_calib() 97 | p.set_sqr1(0) 98 | 99 | root = Tk() 100 | Canvas(root, width = WIDTH, height = 5).pack(side=TOP) # Some space at the top 101 | g = eyeplot.graph(root, width=WIDTH, height=HEIGHT) # make plot objects using draw.disp 102 | g.setWorld(0,-5, NP * delay * 0.001, 5,_('mS'),_('V')) 103 | 104 | if p == None: 105 | g.text(0, 0,_('EYES Hardware Not Found. Check Connections and restart the program'),1) 106 | root.mainloop() 107 | sys.exit() 108 | p.set_voltage(1,5) 109 | 110 | cf = Frame(root, width = WIDTH, height = 10) 111 | cf.pack(side=TOP, fill = BOTH, expand = 1) 112 | 113 | A1 = IntVar() 114 | cb1 = Checkbutton(cf,text =_('ON/OFF'), command = start, variable=A1, fg = 'blue') 115 | cb1.pack(side=LEFT, anchor = SW) 116 | A1.set(0) 117 | 118 | l = Label(cf,text=_('Freq=')) 119 | l.pack(side=LEFT, anchor= SW) 120 | Freq = Entry(cf,width = 10, bg = 'white') 121 | Freq.pack(side=LEFT, anchor = SW) 122 | Freq.insert(END,'4000') 123 | 124 | b = Button(cf,text =_('Xmgrace'), command=xmgrace) 125 | b.pack(side=LEFT, anchor = SW) 126 | 127 | b = Button(cf,text =_('FFT'), command=do_fft) 128 | b.pack(side=LEFT, anchor = SW) 129 | 130 | b = Button(cf,text =_('Save to'), command=save) 131 | b.pack(side=LEFT, anchor = SW) 132 | fn = Entry(cf,width = 10, bg = 'white') 133 | fn.pack(side=LEFT, anchor = SW) 134 | fn.insert(END,'sound.dat') 135 | b = Button(cf,text =_('QUIT'), command=quit) 136 | b.pack(side=RIGHT, anchor = SW) 137 | 138 | 139 | mf = Frame(root) # Message Frame below command frame. 140 | mf.pack(side=TOP, anchor = SW) 141 | msgwin = Label(mf,text = _('Messages'), fg = 'blue') 142 | msgwin.pack(side=LEFT, anchor = SW) 143 | 144 | eyeplot.pop_image('pics/sound-vel.png', _('Velocity of Sound')) 145 | root.title(_('EYES: Velocity of Sound')) 146 | root.mainloop() 147 | -------------------------------------------------------------------------------- /web-connectors/Auto-Tweet-Data/tweet-humidity-temp.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Program to auto tweet humidity and temperature data from ExpEYES 3 | 4 | ExpEYES program developed as a part of GSoC-2015 project 5 | Project Tilte: Sensor Plug-ins, Add-on devices and GUI Improvements for ExpEYES 6 | Mentor Organization:FOSSASIA 7 | Mentors: Hong Phuc, Mario Behling, Rebentisch 8 | Author: Praveen Patil 9 | License : GNU GPL version 3 10 | 11 | ''' 12 | #connect HS1011 between IN1 and GND 13 | #connect LM35 to IN2, OD1 and GND 14 | 15 | import tweepy 16 | from datetime import datetime 17 | import expeyes.eyesj 18 | p= expeyes.eyesj.open() 19 | 20 | cap = p.measure_cap() 21 | if cap< 180: 22 | RH= (cap -163)/0.3 23 | elif 180