-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 75617f5
Showing
5 changed files
with
373 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
USB温度計「TEMPer」のRubyライブラリです。 | ||
|
||
TEMPerについては以下のページをご参照ください。 | ||
http://www.pcsensor.com/index.php?_a=viewProd&productId=6 | ||
|
||
日本では以下のサイトから購入することができます。 | ||
http://www.thanko.jp/product/usb/usb-thermometer.html | ||
http://www.amazon.co.jp/dp/B004FI1570 | ||
|
||
現在 TEMPerV1.2 にのみ対応しています。 | ||
|
||
※以下のデバイスには対応していません。 | ||
TEMPer(V1.2でないもの) | ||
TEMPer1 | ||
TEMPer2 | ||
TEMPerHUM | ||
TEMPerNTC | ||
TEMPer (gold) | ||
|
||
TEMPer と TEMPerV1.2 は製品名および外観は全く同じで見分けがつきません。 | ||
上記サイトで購入したとしても、V1.2でないものが届く可能性がありますのでご注意ください。 | ||
|
||
温度計をPCに接続してlsusbコマンドを実行した時に、 | ||
Bus 002 Device 006: ID 0c45:7401 Microdia | ||
と表示されればV1.2です。(BusとDeviceの値は異なる可能性があります。) | ||
|
||
使い方は test.rb をご参照ください。 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
require 'mkmf' | ||
|
||
have_library( 'usb' ) | ||
|
||
create_makefile( 'temper' ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,308 @@ | ||
/* | ||
* pcsensor.c by Michitaka Ohno (c) 2011 ([email protected]) | ||
* based oc pcsensor.c by Juan Carlos Perez (c) 2011 ([email protected]) | ||
* based on Temper.c by Robert Kavaler (c) 2009 (relavak.com) | ||
* All rights reserved. | ||
* | ||
* Temper driver for linux. This program can be compiled either as a library | ||
* or as a standalone program (-DUNIT_TEST). The driver will work with some | ||
* TEMPer usb devices from RDing (www.PCsensor.com). | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions are met: | ||
* * Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY Juan Carlos Perez ''AS IS'' AND ANY | ||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
* DISCLAIMED. IN NO EVENT SHALL Robert kavaler BE LIABLE FOR ANY | ||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
* | ||
*/ | ||
|
||
|
||
|
||
#include <usb.h> | ||
#include <stdio.h> | ||
|
||
#include <string.h> | ||
#include <errno.h> | ||
#include <signal.h> | ||
|
||
|
||
#define VERSION "1.0.0" | ||
|
||
#define VENDOR_ID 0x0c45 | ||
#define PRODUCT_ID 0x7401 | ||
|
||
#define INTERFACE1 0x00 | ||
#define INTERFACE2 0x01 | ||
|
||
const static int reqIntLen=8; | ||
const static int reqBulkLen=8; | ||
const static int endpoint_Int_in=0x82; /* endpoint 0x81 address for IN */ | ||
const static int endpoint_Int_out=0x00; /* endpoint 1 address for OUT */ | ||
const static int endpoint_Bulk_in=0x82; /* endpoint 0x81 address for IN */ | ||
const static int endpoint_Bulk_out=0x00; /* endpoint 1 address for OUT */ | ||
const static int timeout=5000; /* timeout in ms */ | ||
|
||
const static char uTemperatura[] = { 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 }; | ||
const static char uIni1[] = { 0x01, 0x82, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00 }; | ||
const static char uIni2[] = { 0x01, 0x86, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00 }; | ||
|
||
static int debug=0; | ||
static int calibration=0; | ||
|
||
static usb_dev_handle *find_lvr_winusb(); | ||
|
||
static void usb_detach(usb_dev_handle *lvr_winusb, int iInterface) { | ||
int ret; | ||
|
||
ret = usb_detach_kernel_driver_np(lvr_winusb, iInterface); | ||
if(ret) { | ||
if(errno == ENODATA) { | ||
if(debug) { | ||
printf("Device already detached\n"); | ||
} | ||
} else { | ||
if(debug) { | ||
printf("Detach failed: %s[%d]\n", | ||
strerror(errno), errno); | ||
printf("Continuing anyway\n"); | ||
} | ||
} | ||
} else { | ||
if(debug) { | ||
printf("detach successful\n"); | ||
} | ||
} | ||
} | ||
|
||
static usb_dev_handle* setup_libusb_access() { | ||
usb_dev_handle *lvr_winusb; | ||
|
||
if(debug) { | ||
usb_set_debug(255); | ||
} else { | ||
usb_set_debug(0); | ||
} | ||
usb_init(); | ||
usb_find_busses(); | ||
usb_find_devices(); | ||
|
||
|
||
if(!(lvr_winusb = find_lvr_winusb())) { | ||
if(debug){ | ||
printf("Couldn't find the USB device, Exiting\n"); | ||
} | ||
return NULL; | ||
} | ||
|
||
|
||
usb_detach(lvr_winusb, INTERFACE1); | ||
|
||
|
||
usb_detach(lvr_winusb, INTERFACE2); | ||
|
||
|
||
if (usb_set_configuration(lvr_winusb, 0x01) < 0) { | ||
if(debug){ | ||
printf("Could not set configuration 1\n"); | ||
} | ||
return NULL; | ||
} | ||
|
||
|
||
// Microdia tiene 2 interfaces | ||
if (usb_claim_interface(lvr_winusb, INTERFACE1) < 0) { | ||
if(debug){ | ||
printf("Could not claim interface\n"); | ||
} | ||
return NULL; | ||
} | ||
|
||
if (usb_claim_interface(lvr_winusb, INTERFACE2) < 0) { | ||
if(debug){ | ||
printf("Could not claim interface\n"); | ||
} | ||
return NULL; | ||
} | ||
|
||
return lvr_winusb; | ||
} | ||
|
||
static usb_dev_handle *find_lvr_winusb() { | ||
|
||
struct usb_bus *bus; | ||
struct usb_device *dev; | ||
|
||
for (bus = usb_busses; bus; bus = bus->next) { | ||
for (dev = bus->devices; dev; dev = dev->next) { | ||
if (dev->descriptor.idVendor == VENDOR_ID && | ||
dev->descriptor.idProduct == PRODUCT_ID ) { | ||
usb_dev_handle *handle; | ||
if(debug) { | ||
printf("lvr_winusb with Vendor Id: %x and Product Id: %x found.\n", VENDOR_ID, PRODUCT_ID); | ||
} | ||
|
||
if (!(handle = usb_open(dev))) { | ||
if(debug){ | ||
printf("Could not open USB device\n"); | ||
} | ||
return NULL; | ||
} | ||
return handle; | ||
} | ||
} | ||
} | ||
return NULL; | ||
} | ||
|
||
|
||
static void ini_control_transfer(usb_dev_handle *dev) { | ||
int r,i; | ||
|
||
char question[] = { 0x01,0x01 }; | ||
|
||
r = usb_control_msg(dev, 0x21, 0x09, 0x0201, 0x00, (char *) question, 2, timeout); | ||
if( r < 0 ) | ||
{ | ||
if(debug){ | ||
printf("USB control write"); | ||
} | ||
return; | ||
} | ||
|
||
|
||
if(debug) { | ||
for (i=0;i<reqIntLen; i++) printf("%02x ",question[i] & 0xFF); | ||
printf("\n"); | ||
} | ||
} | ||
|
||
static void control_transfer(usb_dev_handle *dev, const char *pquestion) { | ||
int r,i; | ||
|
||
char question[reqIntLen]; | ||
|
||
memcpy(question, pquestion, sizeof question); | ||
|
||
r = usb_control_msg(dev, 0x21, 0x09, 0x0200, 0x01, (char *) question, reqIntLen, timeout); | ||
if( r < 0 ) | ||
{ | ||
if(debug){ | ||
printf("USB control write"); | ||
} | ||
return; | ||
} | ||
|
||
if(debug) { | ||
for (i=0;i<reqIntLen; i++) printf("%02x ",question[i] & 0xFF); | ||
printf("\n"); | ||
} | ||
} | ||
|
||
static void interrupt_read(usb_dev_handle *dev) { | ||
|
||
int r,i; | ||
char answer[reqIntLen]; | ||
bzero(answer, reqIntLen); | ||
|
||
r = usb_interrupt_read(dev, 0x82, answer, reqIntLen, timeout); | ||
if( r != reqIntLen ) | ||
{ | ||
if(debug){ | ||
printf("USB interrupt read"); | ||
} | ||
return; | ||
} | ||
|
||
if(debug) { | ||
for (i=0;i<reqIntLen; i++) printf("%02x ",answer[i] & 0xFF); | ||
|
||
printf("\n"); | ||
} | ||
} | ||
|
||
static void interrupt_read_temperatura(usb_dev_handle *dev, float *tempC) { | ||
|
||
int r,i, temperature; | ||
char answer[reqIntLen]; | ||
bzero(answer, reqIntLen); | ||
|
||
r = usb_interrupt_read(dev, 0x82, answer, reqIntLen, timeout); | ||
if( r != reqIntLen ) | ||
{ | ||
if(debug){ | ||
printf("USB interrupt read"); | ||
} | ||
return; | ||
} | ||
|
||
|
||
if(debug) { | ||
for (i=0;i<reqIntLen; i++) printf("%02x ",answer[i] & 0xFF); | ||
|
||
printf("\n"); | ||
} | ||
|
||
temperature = (answer[3] & 0xFF) + (answer[2] << 8); | ||
temperature += calibration; | ||
*tempC = temperature * (125.0 / 32000.0); | ||
|
||
} | ||
|
||
usb_dev_handle* pcsensor_open(){ | ||
usb_dev_handle *lvr_winusb = NULL; | ||
|
||
if (!(lvr_winusb = setup_libusb_access())) { | ||
return NULL; | ||
} | ||
|
||
ini_control_transfer(lvr_winusb); | ||
|
||
control_transfer(lvr_winusb, uTemperatura ); | ||
interrupt_read(lvr_winusb); | ||
|
||
control_transfer(lvr_winusb, uIni1 ); | ||
interrupt_read(lvr_winusb); | ||
|
||
control_transfer(lvr_winusb, uIni2 ); | ||
interrupt_read(lvr_winusb); | ||
interrupt_read(lvr_winusb); | ||
|
||
return lvr_winusb; | ||
} | ||
|
||
void pcsensor_close(usb_dev_handle* lvr_winusb){ | ||
usb_release_interface(lvr_winusb, INTERFACE1); | ||
usb_release_interface(lvr_winusb, INTERFACE2); | ||
|
||
usb_close(lvr_winusb); | ||
} | ||
|
||
float pcsensor_get_temperature(usb_dev_handle* lvr_winusb){ | ||
float tempc; | ||
control_transfer(lvr_winusb, uTemperatura ); | ||
interrupt_read_temperatura(lvr_winusb, &tempc); | ||
return tempc; | ||
} | ||
|
||
#ifdef UNIT_TEST | ||
|
||
int main(){ | ||
usb_dev_handle* lvr_winusb = pcsensor_open(); | ||
if(!lvr_winusb) return -1; | ||
float tempc = pcsensor_get_temperature(lvr_winusb); | ||
pcsensor_close(lvr_winusb); | ||
printf("tempc=%f\n", tempc); | ||
return 0; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright (C) 2011 Michitaka Ohno <[email protected]> | ||
* You can redistribute it and/or modify it under GPL2. | ||
*/ | ||
|
||
#include <ruby.h> | ||
#include <usb.h> | ||
#include <stdio.h> | ||
|
||
extern usb_dev_handle* pcsensor_open(); | ||
extern void pcsensor_close(usb_dev_handle* lvr_winusb); | ||
extern float pcsensor_get_temperature(usb_dev_handle* lvr_winusb); | ||
|
||
static VALUE rb_temperature(VALUE self){ | ||
usb_dev_handle* lvr_winusb = pcsensor_open(); | ||
if(!lvr_winusb) return Qnil; | ||
float tempc = pcsensor_get_temperature(lvr_winusb); | ||
pcsensor_close(lvr_winusb); | ||
return rb_float_new(tempc); | ||
} | ||
|
||
Init_temper(void){ | ||
VALUE mTemper; | ||
mTemper = rb_define_module("Temper"); | ||
rb_define_module_function(mTemper, "temperature", rb_temperature, 0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/usr/bin/env ruby | ||
|
||
require './temper.so' | ||
|
||
p Temper.temperature |