Dr.DAQで簡単にデータを解析できるようにするソフト

Dr.DAQをハックしていくと、APIが公開されていた。
Dr.DAQとは、下のようなセンサ回路で、計算機とセントロニクス端子経由でアクセスできる。

秋月電子から購入。
http://akizukidenshi.com/catalog/items2.php?q=DRDAQ&s=score&p=1&r=1&page=

で、専用ソフトがWindows用であるが、サンプリングレート及び、プロット数がきめうちで使いにくい。
個人的には、今から、何件を何ミリ秒ごとに取得 とか、今から何時間を何ミリ秒ごとに取得とかをしたかった。

名前はeasydaq とでもするか。
とりあえず現在できたところまで公開。
一応動作する。後は、時間計測周りの実装と、linux用のデバイスドライバが公開されていたみたいなので、linuxでも使えるように移植しないと。

市教研の算数から再度の追加実装を頼まれるかもしれないので、それまでに完成させたい。

仕様

easydaq [port] [sensor]

使用例

easydaq 1 689

sensor部分は、245 とか書くことで、同時取得可能.

port
1 LPT PORTの1番
2 LPT PORTの2 番, 3とか4もあり
101 USB PORTの1番102とか103もあり
sensor
1 Sound Waveform 音の波形
2 Sound Level 音圧
3 Voltage 電圧
4 Resistance 抵抗
5 pH 水素イオン濃度
6 Temperature 温度
7 Light 光量
8 External 1 外部センサ1
9 External 2 外部センサ2
a the sensor type resistors for EXT1 拡張1
b the sensor type resistors for EXT1 拡張2


CD-ROMでデバイスドライバを入れた後、
パラレルポートにさすだけで本ソフトウェアは使用可能。
ソースコード

//このソースファイルをWindowsでコンパイルするときは、WINをdefine LINUXの時はLINUXを#define
#define WIN

//#define LINUX

/**************************************************************************
 *
 * Filename:    drdaqcon.c
 *
 * Copyright:   Pico Technology Limited 2001
 *
 * Author:      Mike Green
 *
 * Description:
 *   This is a console-mode program that demonstrates how to use the
 *   DRDAQ/22 driver.
 *
 * There are five examples:
 *    Collect a block of samples immediately
 *    Collect a block of samples when a trigger event occurs
 *    Use windowing to collect a sequence of overlapped blocks (USB)
 *    Write a continuous stream of data to a disk file (USB)
 *    Take individual readings
 *
 * To build this application
 *	set up a project for a 32-bit console mode application
 *	add this file to the project
 *	add drdaq32.lib to the project (Borland C only)
 *	add drdaqms.lib to the project (Microsoft C only)
 *	build the project
 *
 * Items marked USB are  only available when the ADC is connected to a
 * Pico USB parallel port.
 *
 * Revision Info: "file %n date %f revision %v"
 *                "file DRDAQCON.C date 15-May-02,11:28:40 revision 1"
 *
 ***************************************************************************/

#include <windows.h>
#include <conio.h>
#include <stdio.h>

#pragma comment(lib,"drdaqms.lib")
/* Definitions of drdaq driver routines */
#include "drdaqw.h"

#define BUFFER_SIZE 	1024
#define TRUE		1
#define FALSE		0
#define MAX_CHANNELS_AT_ONCE	2	// You can change this up to 11 (DRDAQ)

long	times [BUFFER_SIZE];
short	values [BUFFER_SIZE * MAX_CHANNELS_AT_ONCE];
int	port;


/****************************************************************************
 *
 * Collect_individual
 *  this function demonstrates how to take individual readings under
 *  direct program control.
 *
 ****************************************************************************/

void collect_individual (char* daq)
  {
	int iCounter;
  int		sample_no;
  int		c;
  char		str [40];
  short		value;
  short		divider;
  short		places;


  //printf ("Collect individual...\n");
  //printf ("Takes individual readings under program control\n");
  //printf ("Sample from all channels\n");
  //printf ("Press a key to start\n");
 // getch ();

  sample_no = 20;
  /* Sensor name for each channel
  */
  fprintf(stdout,"#");
  //for (c = 1; c <= 9; c++) {
  for ( iCounter = 0; (unsigned)iCounter < strlen( daq ); iCounter++ ) {
	  c = *( daq + iCounter ) - '0';
	  drdaq_get_channel_text (str, c, 3);
	  fprintf (stdout,"%s\t", str);
  }
  //}
  /* Units for each channel
  */
  fprintf (stdout,"\n#");
//  for (c = 1; c <= 9; c++) {
  for ( iCounter = 0; (unsigned)iCounter < strlen( daq ); iCounter++ ) {
	  c = *(daq + iCounter ) - '0';
	  drdaq_get_channel_text (str, c, 4);
	  fprintf (stdout,"%s\t", str);
  }
 // }
  
  fprintf (stdout,"\n");

  while (!kbhit ()) //キーボードに何か文字が入力された.
    {    
    Sleep (100);	//100ミリ秒
    if (++sample_no > 20)
      {
      sample_no = 0;
      fprintf (stderr, "Press any key to stop\n");

      /* Sensor name for each channel
       */
	  //for (c = 1; c <= 9; c++) {
	  for ( iCounter = 0; (unsigned)iCounter < strlen( daq ); iCounter++ ) {
		  c = *(daq + iCounter ) - '0';
		  drdaq_get_channel_text (str, c, 0);
		  fprintf (stderr,"%s\t", str);
	  }
	  //}
	  fprintf (stderr,"\n");

      /* Units for each channel
       */
	  //for (c = 1; c <= 9; c++) {
	  for ( iCounter = 0; (unsigned)iCounter < strlen( daq ); iCounter++ ) {
		  c = *( daq + iCounter ) - '0';
		  drdaq_get_channel_text (str, c, 4);
		  fprintf (stderr,"%s\t", str);
	  }
	  //}
	  fprintf (stderr,"\n");
	}

		/* Read all nine channels
		 *  10 and 11 are the sensor type resistors for EXT1 and EXT2
		 */
		//for (c = 1; c <= 11; c++) {
		for ( iCounter = 0; (unsigned)iCounter < strlen( daq ); iCounter++ ) {
			c = *(daq + iCounter ) - '0';
			if ( c > 9 ) {
				c = c + '0' - 'a' + 10;
			}
			//printf("I Check at !%d!", c);
			value = drdaq_get_value (c);
			if (value == INVALID_DRDAQ_SCALED) {
				fprintf (stdout,"\t");
			} else {
				drdaq_get_channel_info (NULL, NULL, &places, &divider, NULL, c);
				fprintf (stdout,"%0.*f\t", places, ((float) (value)) / divider);
			}
		}
		//}
    fprintf (stdout,"\n");
    }

  getch ();

}


/****************************************************************************
 * 第一引数: 1: LPT1 2:LPT2 101...USBPort
 *
 ****************************************************************************/

int main ( int argc, char** argv)
{
  char 		line [80];
  int		ok;
  int		i;
	char sensor[20];
/*  printf ("drdaq driver example program\n");
  printf ("Version 1.0\n\n");

  printf ("Select the parallel port\n");
  printf ("Use 1 for LPT1,\n"
  	  "    2 for LPT2, etc\n"
          "    101 for USB port 1, etc\n");
  printf ("Port: ");
  scanf ("%d", &port);

  printf ("\n\nOpening the device...\n");
  ok = drdaq_open_unit (port);
  */
	if ( argc > 3 || argc < 2 ) {
		fprintf( stderr, "Usage:consoledaq [port] [sensor]\n" );
		fprintf( stderr, "port 1->LPT1 2->LPT2 x.. etc 101->USB port1 10x.. etc\n" );
		fprintf( stderr, "sensor 1->Sound Waveform\n");
		fprintf( stderr, "sensor 2->Sound Level\n");
		fprintf( stderr, "sensor 3->Voltage\n");
		fprintf( stderr, "sensor 4->Resistance\n");
		fprintf( stderr, "sensor 5->pH\n");
		fprintf( stderr, "sensor 6->Temperature\n");
		fprintf( stderr, "sensor 7->Light\n");
		fprintf( stderr, "sensor 8->External 1\n");
		fprintf( stderr, "sensor 9->External 2\n");
		fprintf( stderr, "sensor a->the sensor type resistors for EXT1\n");
		fprintf( stderr, "sensor b->the sensor type resistors for EXT2\n");
		exit( 1 );
	}
  if ( argc == 2 ) {
	  strcpy( sensor, "123456789ab" );
  } else {
	strcpy( sensor, argv[2] );
  }


  port = atoi( argv[1] );
  ok = drdaq_open_unit( port );
  if (!ok)
    {
    fprintf (stderr, "Unable to open device\n");
    drdaq_get_unit_info (line, sizeof (line), 0, port);
    fprintf (stderr,"%s\n", line);
    exit (99);
    }
  else
    {
    fprintf (stderr, "Device opened successfully\n\n");
    for (i = 0; i < 4; i++)
      {
      drdaq_get_unit_info (line, sizeof (line), i, port);
      fprintf (stderr,"%s\n", line);
      }

      collect_individual (sensor);
  
    /* Essential for USB or NT
     *  not needed for LPT1 on Win95/Win98
     */
		drdaq_close_unit (port);
    }

	return 1;
}