[PYTHON] Utilisez "TSL2561 Illumination Sensor Module Manufacturer Part Number: TSL2561" fabriqué par Strawberry Linux avec Raspberry pi 3 (essai et erreur)

C'est un record de lutte pour l'utilisation du "module de capteur d'éclairement TSL2561 (numéro de pièce du fabricant: TSL2561)" fabriqué par Strawberry Linux avec Rasberry pi 3. Il y a quelques articles sur les capteurs utilisant la puce TSL2561, mais ils ne fonctionnaient pas ou étaient python3. Alors je l'ai essayé avec python2.

Au fait ... je suis nouveau sur python depuis un demi-mois, et je suis nouveau dans le travail électronique, donc j'ai peu de connaissances ... J'espère que cela vous sera utile tout en gardant cela à l'esprit.

Pour le moment, le résumé des pièces nécessaires à utiliser est ici.

Câblage physique

Il est nécessaire de souder la tête de broche pour mettre le capteur livré sur la planche à pain. Après cela, fil en regardant le papier inclus. La configuration des broches GPIO de Raspi n'est pas difficile, car elle apparaîtra dès que vous effectuez une recherche.

Capteur 1pin (GND) -> Raspi 6ème broche Capteur 2 broches (SDA) -> Raspi broche 3 Capteur 3 broches (SCL) -> Raspi 5ème broche Capteur 4 broches (VDD) -> Raspi pin 1

C'est comme ça. TSL2561.png

Activer I2C avec Raspberry pi

Je ne suis pas sûr de ce qu'est I2C. Cependant, selon le wiki, cela semble être un standard pour connecter divers appareils avec une chaîne comme scsi. Quoi qu'il en soit, activez-le pour une utilisation avec raspbian.

Ouvrez le menu de configuration du système d'exploitation à partir de la console ssh et définissez.

$ sudo raspi-config

Sélectionnez le menu dans l'ordre "9 Options avancées" -> "A7 I2C". Il vous sera demandé "Souhaitez-vous que l'interface ARM I2C soit activée?", Alors sélectionnez oui. Il vous sera demandé "Souhaitez-vous que le module du noyau I2C soit chargé par défaut?", Alors sélectionnez oui.

Puis éditez /boot/config.txt comme suit:

$ sudo vi /boot/config.txt
...Ajout du contenu suivant
dtparam=i2c_arm=on

De plus, modifiez / etc / modules comme suit.

$ sudo vi /etc/modules
...Ajout du contenu suivant
snd-bcm2835
i2c-dev

Une fois les paramètres définis, redémarrez Raspy. Assurez-vous que le module du noyau est chargé avec la commande lsmod après le redémarrage.

$ lsmod
...
i2c_dev                 6709  0 
snd_bcm2835            21342  0 
...

Installer des outils

Installez les commandes pour utiliser I2C et la bibliothèque python (peut-être).

$ sudo apt-get install i2c-tools python-smbus

Confirmation d'adresse

Lorsque le câblage est terminé et les outils installés, vérifiez avec la commande si le module capteur est reconnu.

$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- 39 -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Il semble être reconnu à l'adresse 0x39.

... jusqu'à présent, ça va.

Essayez quand même

Tout d'abord, quand je l'ai essayé en référence à cet article, bien que la valeur soit ressortie, elle ne semblait pas liée à la lumière et à l'obscurité. http://qiita.com/masato/items/1dd5bed82b19477b45d8

Donc, quand j'ai enquêté plus loin, je suis arrivé à cet article, mais c'est python3. http://shimobayashi.hatenablog.com/entry/2015/07/27/001708

Hmmm, je ne peux pas y accéder avec le python2 par défaut?

Accéder à I2C depuis python

Si vous lisez l'article ci-dessus et la source de git, il semble que vous devriez utiliser la bibliothèque smbus pour accéder aux périphériques I2C à partir de python. Cependant, je ne sais pas comment l'utiliser, je vais donc l'essayer par essais et erreurs.

Selon la pièce jointe de Strawberry Linux

Ecrivez 0x03 dans le registre interne 0xA0 pour démarrer le fonctionnement du capteur. Lorsque 2 octets sont lus à partir de l'adresse interne 0xAC, cela devient les données brutes de la luminosité du capteur de lumière visible (16 bits, l'octet inférieur vient en premier). Lorsque 2 octets sont lus à partir de l'adresse interne 0xAE, cela devient les données brutes du capteur infrarouge (16 bits, l'octet inférieur vient en premier).

Il y a. ... Hmm Nanno Kotcha.

Quoi qu'il en soit, Raspi semble reconnaître TSL2561 à 0x39, alors je me suis demandé si je devais lire ou écrire 0xA0, 0xAC, 0xAE à partir de là, mais le problème est de savoir comment le faire.

Quand j'ai cherché diversement avec smbus, je suis tombé sur le site suivant. http://raspberrypi.stackexchange.com/questions/8469/meaning-of-cmd-param-in-write-i2c-block-data http://www.raspberry-projects.com/pi/programming-in-python/i2c-programming-in-python/using-the-i2c-interface-2

Je ne suis pas bon en anglais, alors je lis en diagonale autour de la source de l'échantillon et j'essaye de faire des erreurs par intuition. À la suite de divers essais, il semble que vous puissiez lire ou écrire l'adresse interne spécifiée en procédant comme suit.

bus		= smbus.SMBus(1)
bus.write_i2c_block_data(0x39, 0xA0, [0x03])
bus.read_i2c_block_data(0x39, 0xAC ,2)

Le premier smbus.SMBus (1) crée peut-être un objet pour accéder au bus. '1' semble être le même que le 1 spécifié à la fin de "sudo i2cdetect -y 1", et semble spécifier le X du fichier "i2c-X" sous / dev /.

Utilisez la méthode bus.read_i2c_block_data pour lire les données.

bus.read_i2c_block_data (adresse I2C, adresse interne, nombre d'octets de données à lire)

Utilisez la méthode write_i2c_block_data pour écrire des données.

write_i2c_block_data (adresse I2C, adresse interne, tableau de données à écrire)

Avec cela, lorsque j'ai écrit la source de l'échantillon, certaines valeurs comme celles-ci sont sorties. Lorsque vous tenez votre main dessus, la valeur change en réponse. J'ai l'impression que je peux y aller!

#!/usr/bin/python -u
# -*- coding: utf-8 -*-
import smbus
import time
bus	= smbus.SMBus(1)
bus.write_i2c_block_data(0x39, 0x80, [0x03])

while True:
	data 	= self.bus.read_i2c_block_data(self.address, 0xAC ,2)
	raw 	= data[1] << 8 | data[0]
	print "Lumière ambiante: " + str(raw)

	data 	= self.bus.read_i2c_block_data(self.address, 0xAE ,2)
	raw 	= data[1] << 8 | data[0]
	print "Infrarouge: " + str(raw)

	time.sleep(1.0)

Lire la fiche technique du fabricant

Il semble que des données brutes puissent être obtenues, je vais donc essayer de calculer l'éclairement (Lux). Encore une fois, selon la pièce jointe de Strawberry Linux

Veuillez vous référer à la fiche technique du fabricant pour un algorithme qui convertit les données brutes des capteurs visibles et infrarouges en éclairement (lux).

Il y a. Où est le fabricant! À la suite de divers googles tout en réfléchissant, l'URL suivante semble être la fiche technique de la puce TAOS.

https://cdn-shop.adafruit.com/datasheets/TSL2561.pdf

Cool! !! (Vomissement) Est-ce un document anglais, combat, combat, cœur effrayé ~ .... J'arrive à lire en diagonale en me demandant ce que je fais à GW. Puis, à la page 23, il y avait "Calculating Lux", et j'ai trouvé la formule de calcul que j'ai vue dans le git source.

Essayez de classer 1

Je vois, je comprends le flux, alors classons-le.

#!/usr/bin/python -u
# -*- coding: utf-8 -*-

import smbus
import time

#À partir du "TSL2561 Illumination Sensor Module" de Strawberry Linux
#Classe pour acquérir des données avec I2C (partie 1)
# https://strawberry-linux.com/catalog/items?code=12561
# 2016-05-03 Boyaki Machine
class SL_TSL2561:
	def __init__(self, address, channel):
		self.address	= address
		self.channel	= channel
		self.bus		= smbus.SMBus(self.channel)
		self.bus.write_i2c_block_data(self.address, 0x80, [0x03])
		time.sleep(0.5)

	def getVisibleLightRawData(self):
		data 	= self.bus.read_i2c_block_data(self.address, 0xAC ,2)
		raw 	= data[1] << 8 | data[0]	#16 bits avec l'octet inférieur en premier
		return raw

	def getInfraredRawData(self):
		data 	= self.bus.read_i2c_block_data(self.address, 0xAE ,2)
		raw 	= data[1] << 8 | data[0]	#16 bits avec l'octet inférieur en premier
		return raw

	def getLux(self):
		#Acquisition des données brutes du capteur
		VLRD = getVisibleLightRawData()
		IRRD = getInfraredRawData()

		#Ne divisez pas par 0
		if (float(VLRD) == 0):
			ratio = 9999
		else:
			ratio = (IRRD / float(VLRD))

		#Calcul Lux
		if ((ratio >= 0) & (ratio <= 0.52)):
			lux = (0.0315 * VLRD) - (0.0593 * VLRD * (ratio**1.4))
		elif (ratio <= 0.65):
			lux = (0.0229 * VLRD) - (0.0291 * IRRD)
		elif (ratio <= 0.80):
			lux = (0.0157 * VLRD) - (0.018 * IRRD)
		elif (ratio <= 1.3):
			lux = (0.00338 * VLRD) - (0.0026 * IRRD)
		elif (ratio > 1.3):
			lux = 0

		return lux 

if __name__ == "__main__":
	sensor 	= SL_TSL2561(0x39,1) 
	while True:
		print "Lux : " + str(sensor.getLux())
		time.sleep(1.0)

C'était assez simple, mais la lecture du source git le rend plus compliqué et plus long. Quelle est la différence?

Essayez par essais et erreurs

Lors de la lecture de la source git, Gain et Scale apparaissent avant le calcul de l'éclairement. Après avoir étudié ce qu'était le diable, j'ai trouvé la description de «gain élevé (16 ×)» dans «Registre de synchronisation» à la page 15 de la fiche technique, et relu attentivement cette zone.

Apparemment, ce capteur a une spécification qui élargit la plage de détection en combinant «Gain» et «Temps d'intégration». Cela signifie-t-il que la sensibilité sera 16 fois plus élevée avec le gain de hauteur? De plus, si le temps d'intégration est modifié de 402 ms par défaut à 101 ms et 13,7 ms, le temps d'intégration de la valeur de détection sera raccourci et la sensibilité diminuera (= la valeur de sortie diminuera). Avez-vous l'impression que le temps d'exposition est raccourci?

Sur la base de ces informations, modifiez le gain et le temps d'intégration de différentes manières pour afficher la sortie des données brutes. Premièrement, il a été constaté que lorsqu'il était réglé sur High Gain, une valeur d'environ 16 fois était obtenue. On a également constaté que lorsque le temps d'intégration était réglé à 101 ms et 13,7 ms, les valeurs de 101/402 et 13,7 / 402 étaient obtenues.

Par exemple, à Hinata en mai, dans l'état par défaut (le gain est de 1, le temps d'intégration est de 402 ms), la sortie de lumière visible sera de 65535 (valeur maximale de 16 bits) et la valeur correcte ne peut pas être obtenue. Dans un tel cas, il semble que la spécification est de définir le temps d'intégration court et d'obtenir une valeur valide.

Cependant, au moment de High Gain, s'il y avait une certaine quantité de lumière (près de la fenêtre pendant la journée), il y avait un problème que les données brutes étaient fixées à 5047 pour la lumière visible et la lumière infrarouge, ce qui n'a pas pu être résolu. Cela fonctionne bien en basse lumière.

Quoi qu'il en soit, il semble que vous deviez mettre à l'échelle les données brutes avant de faire le calcul de l'éclairement car la sortie change en fonction du réglage. Ce que je n'ai pas vraiment compris ici, c'est sur quel paramètre la formule de calcul de la fiche technique a été écrite. En regardant la source git, lorsqu'elle est à faible gain, les données brutes sont multipliées par 16. Écrivez un exemple de code pour obtenir les données de mesure réelles et comparez-les avec le site suivant.

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12117474762

En conséquence, j'ai conclu que High Gain pourrait être la base. Je me demande si c'est écrit quelque part dans la fiche technique. .. ..

Essayez de classer 2

Reconstruisez la classe en fonction d'essais et d'erreurs. Nous avons préparé une méthode qui vous permet de modifier le gain et le temps d'intégration.

#!/usr/bin/python -u
# -*- coding: utf-8 -*-

import smbus
import time

#À partir du "TSL2561 Illumination Sensor Module" de Strawberry Linux
#Classe pour obtenir des données dans I2C
# https://strawberry-linux.com/catalog/items?code=12561
# 2016-05-03 Boyaki Machine
class SL_TSL2561:
	def __init__(self, address, channel):
		self.address	= address
		self.channel	= channel
		self.bus		= smbus.SMBus(self.channel)
		self.gain 		= 0x00			# 0x00=normal, 0x10=×16
		self.integrationTime 	= 0x02	# 0x02=402ms, 0x01=101ms, 0x00=13.7ms
		self.scale 		= 1.0

		#Initialisation des paramètres du capteur
		self.setLowGain()
		self.setIntegrationTime('default')

	def powerOn(self):
		self.bus.write_i2c_block_data(self.address, 0x80, [0x03])
		time.sleep(0.5)

	def powerOff(self):
		self.bus.write_i2c_block_data(self.address, 0x80, [0x00])

	#Réglé sur Gain élevé(16 fois plus sensible?)
	def setHighGain(self):
		#Lorsqu'il est réglé sur Gain élevé, les données brutes peuvent ne pas être obtenues correctement.
		#Enquête sur la cause requise(5047 Valeur fixe)	
		self.gain 	= 0x10
		data 		= self.integrationTime | self.gain
		self.bus.write_i2c_block_data(self.address, 0x81, [data])
		self.calcScale()

	# Low Gain(default)Mis à
	def setLowGain(self):
		self.gain 	= 0x00
		data 		= self.integrationTime | self.gain
		self.bus.write_i2c_block_data(self.address, 0x81, [data])
		self.calcScale()

	#Réglage du temps d'intégration (temps pour une détection?)
	# val = shor, middle, logn(default)
	def setIntegrationTime(self, val):
		if val=='short':
			self.integrationTime 	= 0x00	# 13.7ms scale=0.034
		elif val=='middle':
			self.integrationTime 	= 0x01 	# 101ms	 scale=0.252
		else:
			self.integrationTime 	= 0x02  # defaultVal 402ms  scale=1.0
		data = self.integrationTime | self.gain
		self.bus.write_i2c_block_data(self.address, 0x81, [data])
		self.calcScale()

	def getVisibleLightRawData(self):
		data 	= self.bus.read_i2c_block_data(self.address, 0xAC ,2)
		raw 	= data[1] << 8 | data[0]	#16 bits avec l'octet inférieur en premier
		return raw

	def getInfraredRawData(self):
		data 	= self.bus.read_i2c_block_data(self.address, 0xAE ,2)
		raw 	= data[1] << 8 | data[0]	#16 bits avec l'octet inférieur en premier
		return raw

	def getRawData(self):
		data 	= self.bus.read_i2c_block_data(self.address, 0xAC ,4)
		VL 		= data[1] << 8 | data[0]	#Lumière visible 16 bits, octet inférieur en premier
		IR 		= data[3] << 8 | data[2]	#Infrarouge 16 bits, octet inférieur en premier
		return (VL,IR)

	def calcScale(self):
		_scale = 1.0
		#Échelle par intégration
		if self.integrationTime == 0x01:	# middle
			_scale = _scale / 0.252
		elif self.integrationTime == 0x00:	# short
			_scale = _scale / 0.034
		
		#Échelle par gain
		if self.gain == 0x00 :				# gain 1
			_scale = _scale * 16.0

		self.scale = _scale

	def getLux(self):
		#Acquisition des données brutes du capteur
		raw  = self.getRawData()

		#Implémentation pour générer une erreur lorsque 65535
		if raw[0] == 65535 or raw[1] == 65535:
			return "Range Over"

		#Mettre à l'échelle les données brutes avec les paramètres du capteur
		VLRD = raw[0] * self.scale
		IRRD = raw[1] * self.scale

		#Ne divisez pas par 0
		if (float(VLRD) == 0):
			ratio = 9999
		else:
			ratio = (IRRD / float(VLRD))

		#Calcul Lux
		if ((ratio >= 0) & (ratio <= 0.52)):
			lux = (0.0315 * VLRD) - (0.0593 * VLRD * (ratio**1.4))
		elif (ratio <= 0.65):
			lux = (0.0229 * VLRD) - (0.0291 * IRRD)
		elif (ratio <= 0.80):
			lux = (0.0157 * VLRD) - (0.018 * IRRD)
		elif (ratio <= 1.3):
			lux = (0.00338 * VLRD) - (0.0026 * IRRD)
		elif (ratio > 1.3):
			lux = 0

		return lux 


if __name__ == "__main__":
	sensor 	= SL_TSL2561(0x39,1) 
	sensor.powerOn()
	# sensor.setHighGain()
	sensor.setIntegrationTime('default')
	while True:
		print "Lux : " + str(sensor.getLux())
		time.sleep(1.0)

À la fin

En utilisant la classe ci-dessus, vous pouvez obtenir une telle valeur. Cependant, le problème du gain élevé n'a pas été résolu. Je ne peux pas confirmer si la mise en œuvre est correcte en premier lieu ...

En regardant la source de l'échantillon de la feuille de données, lors de l'accès à l'adresse interne (est-ce un registre?), Il s'agit de 0xAX ou 0x8X. En regardant les spécifications de "Register Set", seuls 0h à Fh sont écrits. Si vous devinez d'après la source s'il s'agit de 0xA ou 0x8, je pense que vous spécifiez le type de valeur à acquérir, mais je ne connais pas la vérité. Quelle que soit l'adresse que vous spécifiez, la même valeur sera obtenue, donc je soupçonne que python la convertit en une bonne. S'il vous plaît laissez-moi savoir si quelqu'un sait.

Si vous vérifiez la valeur des données brutes comme il convient et changez les paramètres de gain et de temps d'intégration lorsque la valeur limite est proche, vous pouvez mesurer de manière transparente une large plage.

Si c'est utile, je suis heureux.

Recommended Posts

Utilisez "TSL2561 Illumination Sensor Module Manufacturer Part Number: TSL2561" fabriqué par Strawberry Linux avec Raspberry pi 3 (essai et erreur)
Utilisez le «module de capteur d'éclairage TSL2561 (numéro de pièce du fabricant: TSL2561)» fabriqué par Strawberry Linux avec Rasberry pi 3 (résumé)
Utilisez le «module de capteur 9 axes MPU-9250 (numéro de pièce du fabricant: MPU-9250)» fabriqué par Strawberry Linux avec Rasberry pi 3.
Un mémo pour utiliser simplement le capteur d'éclairement TSL2561 avec Raspberry Pi 2
Utiliser le capteur Grove avec Raspberry Pi
Grove - Capteur de température et d'humidité (DHT11) avec Raspberry Pi
Utilisez le capteur d'éclairement numérique TSL2561 avec Raspberry Pi
Ubuntu 20.04 sur raspberry pi 4 avec OpenCV et utilisation avec python
Utilisez NeoPixel avec la tarte aux framboises