Salut Flexbrane,
Je viens de modifier le code pour un DHT22. Il n'est pas un capteur SPI et le protocol est plutôt proche du 1-wire.
Mais avec les problèmes de timing que j'ai lorsque je roule mjpg_streamer J'ai décidé d'utiliser le SPI , Style capture du signal chronologique, pour décoder avec la précision de l'horloge.
Ce n'est pas ce que tu veux mais cela te montrera comment les utiliser. Du moins comment y accéder.
Ce que je vois vitement c'est de faire un xfer2 de 2 octets pour lires les valeurs. et un xfer2 de 4 octets donc les deux derniers auront la configuration. Peut être pour la configuration , il faudra un 5 ième octet au cas ou.
La commande xfer2 transfère la liste en écriture et retourne la liste avec les valeurs lues.
Voici mon code python. Il faut installer py-spidev.
Code: Select all
cat dht22spi.py
#!/usr/bin/python
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
# dht22spi.py
#
# Read dht22 sensor using Raspberry Pi spi
#
# Daniel Perron
# 15 February 2014
#
import spidev
import time
class dht22spi():
def __init__(self):
self.spi = spidev.SpiDev()
self.speed = 500000
self.spi.open(0,0)
self.max_speed_hz=self.speed
self.Bits = [ 128, 64, 32, 16, 8, 4, 2, 1]
self.DHT22Reg = [0,0,0,0,0]
#ok 10ms should be good enough
MaxBits = 0.010 * self.speed
self.ArraySize = int(MaxBits / 8)
self.TotalBits = self.ArraySize * 8
self.D = bytearray(self.ArraySize)
# set first 1.5 ms Low and the rest high
End = (0.0015 * self.speed)/8
for i in range(self.ArraySize):
if i > End:
self.D[i] = 255
else:
self.D[i] = 0
def GetBit(self,index):
byteIndex = index / 8
if (self.Data[byteIndex] & self.Bits[index % 8]) == 0:
return False
return True
def GetNextDelay(self):
if self.LastIndex >= self.TotalBits:
return 0
Index = self.LastIndex
LastBit = self.GetBit(Index)
while Index<self.TotalBits:
if not (self.GetBit(Index) == LastBit):
Delta = Index - self.LastIndex
Deltaus = Delta * 1000000 / self.speed
self.LastIndex = Index
return Deltaus
Index += 1
## this routine return three values
# temperature , Humidity and an boolean value to tell if the data is Valid
def Read(self):
self.LastIndex=0
self.Data = list(self.D)
self.spi.xfer2(self.Data)
#first get rid off start
self.GetNextDelay()
#now get rid off wait
self.GetNextDelay()
#now get rid off Ack
self.GetNextDelay()
#and the the high Ack
self.GetNextDelay()
for Idx in range(5):
self.DHT22Reg[Idx]=0
for bitidx in range(8):
#low parts
self.GetNextDelay()
#read High Parts
delai = self.GetNextDelay()
if delai < 12:
return [ None , None , False]
if delai > 80:
return [ None , None , False]
if delai > 43:
self.DHT22Reg[Idx] |= self.Bits[bitidx]
#checksum
Checksum = 0;
for Idx in range(4):
Checksum += self.DHT22Reg[Idx]
Checksum %= 256
#print "CheckSum= ", Checksum
if Checksum == self.DHT22Reg[4]:
Temp= ((self.DHT22Reg[2] & 127) * 256 + self.DHT22Reg[3]) / 10.0
if (self.DHT22Reg[2] & 128) == 128:
Temp = -Temp
Humidity= (self.DHT22Reg[0] * 256 + self.DHT22Reg[1]) / 10.0
else:
return [ None , None , False]
return [Temp , Humidity , True]
if __name__ == '__main__':
dht22 = dht22spi()
import time
value = dht22.Read()
time.sleep(0.5)
value = dht22.Read()
if value[2]:
print "Temperature = ", value[0], " Celsius"
print "Humidity = ", value[1], " %"
else:
print "Unable to read dht22 sensor"
et le code en C
Code: Select all
/* dht22spi
* SPI device interface to read DHT22 sensor
*
* Copyright (c) February 2014 Daniel Perron
*
*
* Software inspire from
* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob_plain;f=Documentation/spi/spidev_test.c
* Copyright (c) 2007 MontaVista Software, Inc.
* Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* Cross-compile with cross-gcc -I/path/to/cross-kernel/include
*/
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <malloc.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
static void pabort(const char *s)
{
perror(s);
abort();
}
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 500000;
static uint16_t delay;
static unsigned char Bits[8]={128,64,32,16,8,4,2,1};
static void transfer(int fd, unsigned char *ArrayTx, unsigned char *ArrayRx, int ArraySize)
{
int ret;
ArrayRx[0]=0;
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)ArrayTx,
.rx_buf = (unsigned long)ArrayRx,
.len = ArraySize,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
}
int GetBit(unsigned char * Array, int bitIdx)
{
int ByteIdx = bitIdx/8;
if( (Array[ByteIdx] & Bits[bitIdx % 8]) == 0)
return 0;
return 1;
}
int GetNextDelay(unsigned char * Array, int * bitIdx, int MaxBit)
{
int index,Lastbit,delta;
if( *bitIdx >= MaxBit) return(0);
index = *bitIdx;
Lastbit = GetBit(Array,index);
while(index < MaxBit)
{
if(GetBit(Array,++index) != Lastbit)
{
delta = index - *bitIdx;
*bitIdx = index;
return( (int) (1000000.0 * delta / speed)); // return value in usec
}
}
return(0);
}
int DecodeArray(unsigned char *ArrayIn,unsigned char *ArrayOut, int TotalBit)
{
int ByteIdx,BitIdx;
int BitPointer=0;
int HighPulse;
//first get rid off start
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
//get rid off wait
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
//get rid off ACK
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
//get rid off ACK
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
for(ByteIdx=0;ByteIdx<5;ByteIdx++)
{
ArrayOut[ByteIdx]=0;
for(BitIdx=0;BitIdx<8;BitIdx++)
{
// get low level
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
// get High level
HighPulse = GetNextDelay(ArrayIn,&BitPointer,TotalBit);
if(HighPulse < 5) return 0;
if(HighPulse > 80)return 0;
if(HighPulse > 43)
ArrayOut[ByteIdx]|= Bits[BitIdx];
}
}
return 1;
}
int main(int argc, char *argv[])
{
int ret = 0;
int fd;
int loop;
unsigned char checkSum;
unsigned char ArrayOut[5];
float Temperature,Humidity;
fd = open("/dev/spidev0.0", O_RDWR);
if (fd < 0)
pabort("can't open device");
/*
* spi mode
*/
mode = 0;
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
pabort("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
pabort("can't get spi mode");
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get max speed hz");
// use a array size fpr 10ms;
int BitSize = (int) ( 0.008 * speed);
int ArraySize = BitSize / 8;
int TotalBit = ArraySize * 8;
unsigned char * Array= (unsigned char *) malloc(ArraySize);
// need to have the 1.5 ms to 0
int startOfRx = (int) (0.0015 * speed) / 8;
memset(Array,0, startOfRx);
memset(&Array[startOfRx],0xff, ArraySize-startOfRx);
transfer(fd,Array, Array,ArraySize);
if(DecodeArray(Array,ArrayOut,TotalBit))
{
checkSum=0;
for(loop=0;loop<4;loop++)
checkSum+=ArrayOut[loop];
if(checkSum!=ArrayOut[4])
printf("Checksum invalid\n");
else
{
Temperature = ((int) (ArrayOut[2]&0x7f) * 256 + ArrayOut[3])/10.0;
if((ArrayOut[2] & 0x80)== 0x80)
Temperature = -(Temperature);
Humidity = ((int) ArrayOut[0]*256 + ArrayOut[1])/10.0;
printf("Temperature = %5.1f Celsius\n",Temperature);
printf("Humidity = %5.1f %%\n",Humidity);
}
}
else
printf("Unable to read DHT22 sensor\n");
close(fd);
free(Array);
return ret;
}