

------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
ソースコード集(2019/10/1)

1.　書籍の本文に対応する、タイトルに引き続いて、ソースコードが置かれています。
2.　ソースコードは---と---の間に記述されています。
3.　ソースコードが対応する言語は、プログラムの先頭で区別されます。
------------------------------------------------------------------------------------------------------------------------------------
対応する言語の区別

1.　# で始まっているのは、bashスクリプトです
2.　(* Mathematica *) で始まっているのは、Mathematicaプログラムです
3.　// で始まっているのは、Arduino(ATtiny85）のためのCプログラムです
4.　// Node.js で始まっているのは、Node.jsのためのJavaScriptです
------------------------------------------------------------------------------------------------------------------------------------
使い方

利用者は必要部分をコピーし、Mathematicaであればノートブックにペーストして使ってください。bash、C、Arduino、Node.jsであれば、使っているエディタ上にペーストして使います。
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
3.3 PWM:シェルスクリプトでPWMを設定
------------------------------------------------------------------------------------------------------------------------------------
#!/bin/bash
#control PWM
cd /sys/class/pwm/pwmchip0
#
sudo sh -c "echo 0 > export"
cd pwm0
sudo chmod 666 period
sudo chmod 666 duty_cycle
sudo chmod 666 enable
------------------------------------------------------------------------------------------------------------------------------------
3.3 PWM:MathematicaからPWMを設定
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* PWM control *)
	process =  StartProcess[$SystemShell,  ProcessDirectory -> "/sys/class/pwm/pwmchip0/pwm0"];
	WriteLine[process, "echo 800000000 > period"];
	WriteLine[process, "echo 400000000 > duty_cycle"];
	WriteLine[process, "echo 1 > enable"];
------------------------------------------------------------------------------------------------------------------------------------
3.4 スタンドアローンシステム:ピンの電圧を検出する方法
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* pin monitoring to shutdown *)
process= StartProcess[$SystemShell];
WriteLine[process, "echo '7' > /sys/class/gpio/export"];

(* any program lines *)

WriteLine[process, "cat /sys/class/gpio/gpio7/value"];
If[ReadLine[process] == "0",
  $Epilog:= Run["sudo shutdown -t 2"];
  Exit[]
  ];

(* any program lines *)
------------------------------------------------------------------------------------------------------------------------------------
3.5 外部モジュールの制御をサポートする関数:文字ー16進数文字列変換
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* hex to character *)
str= "2";
hex= "0x" <> IntegerString[ToCharacterCode[str], 16]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* character to hex *)
FromCharacterCode[FromDigits[StringReplace[hex, "0x" -> ""], 16]]
------------------------------------------------------------------------------------------------------------------------------------
3.5 外部モジュールの制御をサポートする関数:I2Cのための文字列変換
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* character to hex list *)
str = "@123456";
hexList = Map["0x" <> IntegerString[#, 16] &, ToCharacterCode[str]]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* buildup I2C command *)
chipAdr = "0x3e";
StringRiffle[{"i2cset -y 1", chipAdr, Apply[Sequence, hexList], "i"}]
------------------------------------------------------------------------------------------------------------------------------------
3.5 外部モジュールの制御をサポートする関数:2の補数表現の変換
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* base 16 string to integer *)
If[# > 32767, -65536 + #, #] &[FromDigits["8000", 16]]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* integer(-32768~0~32767) to hex string *)
IntegerString[If[# < 0, 65536 + #, #], 16, 4] &[-32768]
------------------------------------------------------------------------------------------------------------------------------------
3.5 外部モジュールの制御をサポートする関数:バイトー整数変換
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* byte to integer *)
(* Get register value *)
	rGet[reg_] := StringTrim[RunProcess[{"i2cget", "-y", "1", chipAdr, reg}, "StandardOutput"]];
(* Get unSigned and Short Integer *)
	usGet[reg1_, reg2_] := (
	   	r = Flatten[{rGet[reg1], rGet[reg2]}];
 	  	r1 = Map[FromDigits[#, 16] &, StringReplace[r, "0x" -> ""]];
	   	BitShiftLeft[r1[[1]], 8] + r1[[2]]
   );
(* Get Signed Short Integer *)
	ssGet[reg1_, reg2_] := (
 	  	r = Flatten[{rGet[reg1], rGet[reg2]}];
	   	r1 = Map[FromDigits[#, 16] &, StringReplace[r, "0x" -> ""]];
	   	r2 = BitShiftLeft[r1[[1]], 8] + r1[[2]];
	   	If[r2 > 32767, -32768 + (r2 - 32768), r2]
   );
------------------------------------------------------------------------------------------------------------------------------------
3.5 外部モジュールの制御をサポートする関数:カルマンフィルタ
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* Kalman filter *)
kalman[name_] := Module[{nVobsEq, nVcondEq, kGain, wPrevious, xPrevious, xForecast, xEstimated},
   
   initPrev[name[xp_, wp_]] ^:= (
     	xPrevious = xp(* previous observed value *);
     	wPrevious = wp(* previous variance of estimated values *);
     );
   setVariance[name[ceq_, oeq_]] ^:= (
     	nVcondEq = ceq(* noise variance of condition equation *);
     	nVobsEq = oeq(* noise variance of observation equation *);
     );
   estimated[name[xObs_]] ^:= (
     	xForecast = xPrevious(* local level model *);
     	wPrevious = wPrevious + nVcondEq;
     	kGain = wPrevious/(wPrevious + nVobsEq);
     	wPrevious = (1 - kGain)*wPrevious;
     	xPrevious = xForecast + kGain*(xObs - xForecast);
     	Return[xPrevious]
     	);
   ];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* construct instance *)
kalman[gyro];
initPrev[gyro[0, 0.01]];
setVariance[gyro[0.1, 1]]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* show results *)
u= Table[Sin[(2 π i)/13.0]+RandomReal[NormalDistribution[0,1]],{i,100}];
v=Table[estimated[gyro[u[[i]]]],{i,100}];
ListLinePlot[{u,v}]
------------------------------------------------------------------------------------------------------------------------------------
5.1 フルカラーLED モジュール:Mathematicaで制御してみる
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* start process *)
process = StartProcess[$SystemShell];
WriteLine[process, "gpio -g mode 17 out"];
WriteLine[process, "gpio -g mode 18 out"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* LED on *)
WriteLine[process, "gpio -g write 18 1"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* LED off *)
WriteLine[process, "gpio -g write 18 0"];
------------------------------------------------------------------------------------------------------------------------------------
5.3 スイッチの制御:検出方法 1
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* initialize switch 1 *)
(* set interrupt service to GPIO Pin7 *)
	process = StartProcess[$SystemShell];
	WriteLine[process, "echo '7' > /sys/class/gpio/export"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* initialize switch 1 *)
	WriteLine[process, "cat /sys/class/gpio/gpio7/value"];
	ReadLine[process]
------------------------------------------------------------------------------------------------------------------------------------
5.3 スイッチの制御:検出方法 2
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* start-up shell process *)
	process = StartProcess[$SystemShell];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* BCM12 (GPIO_GEN26) pin set to input *)
	WriteLine[process, "gpio -g mode 12 in"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read BCM12 pi status *)
	WriteLine[process, "gpio -g read 12"];
	ReadLine[process]
------------------------------------------------------------------------------------------------------------------------------------
5.3 スイッチの制御:オブジェクト指向を適用した４チャンネルタッチスイッチの検出
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* switch data *)
gpioPin = Association[a -> 19, b -> 16, c -> 26, d -> 20];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* initialize switch *)
gpio[nam_] := Module[{process, comstr, schTask},
  	set[nam[pin_]] ^:= (
    	process = StartProcess[$SystemShell];
    	comstr = "gpio -g read " <> ToString[pin];
    	schTask = CreateScheduledTask[WriteLine[process, comstr];
      	status[nam] = ReadLine[process], 0.1];
    	);
  	start[nam] ^:= StartScheduledTask[schTask];
]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* start switch *)
	Map[gpio, Keys[gpioPin]];
	Map[set, KeyValueMap[#1[#2] &, gpioPin]];
	Map[start, Keys[gpioPin]];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read switch *)
	{Dynamic[status[a] == "1"], Dynamic[status[b]], Dynamic[status[c]], Dynamic[status[d]]}
------------------------------------------------------------------------------------------------------------------------------------
6.1 Arduino IDEによるプログラミング:millis関数を用いたLED点滅プログラム
------------------------------------------------------------------------------------------------------------------------------------
//Arduino
//LED blinker
const int ledPin =  1;
int ledState = 0;
unsigned long previousMillis = 0;
int long interval = 2000;

void setup() {                
 pinMode(ledPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();
   if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    ledState=ledState^1;
    digitalWrite(ledPin,(ledState) ? LOW : HIGH);
   }
}
------------------------------------------------------------------------------------------------------------------------------------
6.1 Arduino IDEによるプログラミング:Arduinoのソースコードの構造と実行
------------------------------------------------------------------------------------------------------------------------------------
//Arduino
//tact-switch controller
#define led_pin 1
#define button_pin 2

void setup() {
  pinMode(led_pin, OUTPUT);
  pinMode(button_pin, INPUT_PULLUP);
}

void loop() {
   if(digitalRead(button_pin)==0){
      digitalWrite(led_pin, HIGH);
       }
   else{
      digitalWrite(led_pin, LOW); 
       }
 }
------------------------------------------------------------------------------------------------------------------------------------
//Arduino
//PWM control for LED
void setup() 
{
  pinMode (0, OUTPUT);  // OC0A
  pinMode (1, OUTPUT);  // OC0B
  pinMode (4, OUTPUT);  // OC1B
  
  // Oscillator 0, channel A
  TCCR0A = _BV (WGM00) | _BV (WGM01) | _BV (COM0A1); // fast PWM, clear OC0A on compare
  TCCR0B = _BV (CS00);          // fast PWM, top at 0xFF, no prescaler
  OCR0A = 63;                   // duty cycle (25%)

  // Oscillator 0, channel B
  TCCR0A |= _BV (COM0B1);        // clear OC0B on compare
  OCR0B = 63;                    // duty cycle (25%)

  // Oscillator 1, channel B
  TCCR1 = _BV (CS10);           // no prescaler
  GTCCR = _BV (COM1B1) | _BV (PWM1B);  //  clear OC1B on compare 
  OCR1B = 31;                   // duty cycle (25%)
  OCR1C = 127;                  // frequency
  }

void loop() { }
------------------------------------------------------------------------------------------------------------------------------------
6.2 I2Cを通じてRaspberry PiからDigisparkを制御する
------------------------------------------------------------------------------------------------------------------------------------
//Arduino
//LED controller 
//ATtiny85 slave program
#define I2C_SLAVE _ADDRESS 0x5A // an arbitrary 7-bit address
#define LED_PIN         1      // DigiSpark LED pin1

#include <TinyWireS.h>  // I2C routines

#ifndef TWI_RX _BUFFER _SIZE
#define TWI_RX _BUFFER _SIZE ( 16 )
#endif
//
int ledState = 0;
unsigned long previousMillis = 0;

volatile uint8_t i2c_regs[] =
{   0xDE,   // initial value of registers
    0xAD, 
    0xBE, 
    0xEF, 
};

volatile byte reg_position;
const byte reg_size = sizeof(i2c_regs);

void requestEvent()
{  reg_position %= reg_size;
    TinyWireS.send(i2c_regs[reg_position]);
    reg_position++;
}

void receiveEvent(uint8_t howMany)
{
    // Sanity check
    if ((howMany < 1) || (howMany > TWI_RX _BUFFER _SIZE)) return;
    
    reg_position = TinyWireS.receive();
    howMany--;

    while(howMany--)
    {
        reg_position %= reg_size;
        i2c_regs[reg_position] = TinyWireS.receive();
        reg_position++;
    }
}

void setup()
{  pinMode(LED_PIN,OUTPUT);
    mt08Blink(LED_PIN, 2);               //LED blink 2-times following bootup

    TinyWireS.begin(I2C_SLAVE _ADDRESS);
    TinyWireS.onReceive(receiveEvent);
    TinyWireS.onRequest(requestEvent);
}

void loop()
{  TinyWireS_stop _check();
   int long interval= i2c_regs[0]; // get data of register0 changed through I2C
   unsigned long currentMillis = millis(); // get time in milli second
   
   if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    ledState=ledState^1;    // flip-flop led status using XOR
    digitalWrite(LED_PIN,(ledState) ? LOW : HIGH);  // C style IF
   } 
}

void mt08Blink(byte led, byte times)
{
  times *= 2;
  while(times > 0) {
    digitalWrite(led,(times & 0x01) ? LOW : HIGH);
    delay (200);
    times--;
  }
}
------------------------------------------------------------------------------------------------------------------------------------
6.3 Raspberry PiからDigisparkのフルカラーLEDを制御する:LEDtest.h
------------------------------------------------------------------------------------------------------------------------------------
// .h file
// definition of function names for LEDtest
//
#ifndef LedTest_h
#define LedTest_h

class LedTest
{ public:
   LedTest(int pin);  //constructor
   void set(int valInt ;

private:
  int ledPin;
  int onInterval;
  int offInterval;
 };
#endif
------------------------------------------------------------------------------------------------------------------------------------
6.3 Raspberry PiからDigisparkのフルカラーLEDを制御する:LEDtest.cpp
------------------------------------------------------------------------------------------------------------------------------------
// .cpp file
// definition of Class for LEDtest
//
#include <Arduino.h>
#include "LedTest.h"

LedTest::LedTest(int pin)
{ ledPin = pin;   
  onInterval = 10; 
  pinMode(ledPin, OUTPUT);
}

void LedTest::set(int valInt)
{ onInterval= valInt;
  offInterval = 255- onInterval; // LED on interval must be 0 to 255
  digitalWrite(ledPin, HIGH);
  delayMicroseconds(onInterval);
  digitalWrite(ledPin, LOW);
  delayMicroseconds(offInterval);
}
------------------------------------------------------------------------------------------------------------------------------------
6.3 Raspberry PiからDigisparkのフルカラーLEDを制御する:LEDtest.ino 1: ATtiny85の動作テストプログラム
------------------------------------------------------------------------------------------------------------------------------------
// .ino file
// Arduino
// ATtiny85 test
#include <LedTest.h>

LedTest ledRed = LedTest(1);
LedTest ledBlue = LedTest(4); 
LedTest ledGreen = LedTest(3);

void setup() { }

void loop()
{ ledRed.set(10);
   ledBlue.set(10);
   ledGreen.set(10);
}
------------------------------------------------------------------------------------------------------------------------------------
6.3 Raspberry PiからDigisparkのフルカラーLEDを制御する:LEDtest.ino 2: I2Cバスで結ばれたRaspberry Piからの命令にしたがって、ATtiny85がLEDを制御するプログラム
------------------------------------------------------------------------------------------------------------------------------------
// .ino file
// Arduino
// control LED
#include "LedTest.h"
#include <TinyWire.h>  // I2C routines
#define I2C_SLAVE _ADDRESS 0x5A // the 7-bit address

#ifndef TWI_RX _BUFFER _SIZE
#define TWI_RX _BUFFER _SIZE (16)
#endif
//

volatile uint8_t i2c_regs[] =
{10,  0, 10,  0, 10,  0};

volatile byte reg_position;
const byte reg_size = sizeof(i2c_regs);

LedTest ledRed = LedTest(1); // construct instances
LedTest ledBlue = LedTest(4); 
LedTest ledGreen = LedTest(3);

void requestEvent()
{  reg_position %= reg_size;
    TinyWire.send(i2c_regs[reg_position]);
    reg_position++;
}

void receiveEvent(int howMany)
{   // Sanity check
    if ((howMany < 1) || (howMany > TWI_RX _BUFFER _SIZE)) return;
    
    reg_position = TinyWire.receive();
    howMany--;

    while(howMany--)
    {   reg_position %= reg_size;
        i2c_regs[reg_position] = TinyWire.receive();
        reg_position++;
    }
}

void setup()
{ TinyWire.begin(I2C_SLAVE _ADDRESS);
    TinyWire.onReceive(receiveEvent);
    TinyWire.onRequest(requestEvent);
  }

void loop()
{ int intRed= i2c_regs[0]; // get data of registers changed through I2C
  ledRed.set( intRed );
  int intBlue= i2c_regs[2];
  ledBlue.set( intBlue );
  int intGreen= i2c_regs[4];
  ledGreen.set( intGreen );
}
------------------------------------------------------------------------------------------------------------------------------------
6.4 ATtiny85のI2Cチェーン:ATtiny-A: マスタとしてもスレーブとしても働くノード
------------------------------------------------------------------------------------------------------------------------------------
//Arduino
//ATtiny85-A
#include <TinyWire.h>

#define led_pin 1
#define button_pin 3
#define error_led _pin 4

byte own_address = 9; //my address is 0x09
byte slave_address = 10; //ATtiny85-B address is 0x0a


void setup() {
  // config led_pin as Output for driving an LED
  pinMode(led_pin, OUTPUT);
  // config error_led _pin as Output for driving an LED
  pinMode(error_led _pin, OUTPUT);
  // config button_pin als INPUT for a connected button (normally open; connects to GND)
  pinMode( button_pin, INPUT_PULLUP);
  
  // config TinyWire library for I2C slave functionality
  TinyWire.begin( own_address );
  // set slave receive callback
  TinyWire.onReceive( onI2CReceive );
}

void loop() {
  // check, if the button was pressed
  if(digitalRead(button_pin) == 0) {
    // begin a master transmission with the specified slave address
    // the library temporarily takes the functionality of a master during sending
    TinyWire.beginTransmission( slave_address );
    // fill the send buffer
    TinyWire.send('b');
    // execute the master sending and check for an error
    // returns 0 if there was no error (otherwise you can find the different error code definitions in TinyWire.h)
    if(TinyWire.endTransmission()!=0) {
      // turn on the error LED, if there was an error
      digitalWrite(error_led _pin, HIGH);
    }
    delay(300);
    // reset error LED after a short delay
    digitalWrite(error_led _pin, LOW);
  }
}

void onI2CReceive(int howMany){
  // loops, until all received bytes are read
  while(TinyWire.available()>0){
    // toggles the led everytime, when an 'a' is received
    if(TinyWire.read()=='a') digitalWrite(led_pin, !digitalRead(led_pin));
  }
}
------------------------------------------------------------------------------------------------------------------------------------
6.4 ATtiny85のI2Cチェーン:ATtiny-B: スレーブとして待機しているノード
------------------------------------------------------------------------------------------------------------------------------------
//Arduino
//ATtiny85-B
# include < TinyWire.h >
# define led_pin 1
          
byte own_address = 10; //my address is 0x0a
void setup () {
	pinMode (led_pin, OUTPUT);
	// config TinyWire library for I2C slave functionality
	TinyWire.begin ( own_address );
	// sets callback for the event of a slave receive
    TinyWire.onReceive ( onI2CReceive );
    }
          
void loop () {
              }
          
/*
I2C Slave Receive Callback :
Note that this function is called from an interrupt routine and shouldn't take long to execute
*/
void onI2CReceive (int howMany) {
    // loops, until all received bytes are read
    while (TinyWire.available () > 0) {
         // toggles the led everytime, when an 'b' is received
         if (TinyWire.read () ==' b') digitalWrite (led_pin, ! digitalRead (led_pin));
    	}
 }
------------------------------------------------------------------------------------------------------------------------------------
7.1 Dovewill (Adafruit) 10 DOF  6軸と方位と温度・気圧モジュール
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read LSM303DLHC accelerometer *)
chipAdr = "0x19";
rGet[reg_] := StringTrim[RunProcess[{"i2cget", "-y", "1", chipAdr, reg}, "StandardOutput"]];
{rGet["0x20"], rGet["0x21"], rGet["0x22"]}
------------------------------------------------------------------------------------------------------------------------------------
7.1 Dovewill (Adafruit) 10 DOF  6軸と方位と温度・気圧モジュール:LSM303DLHC 磁場センサ
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* initialize LSM303DLHC magneto meter *)
chipAdr = "0x1e";
process = StartProcess[$SystemShell];
rGet[r_] := (WriteLine[process, StringRiffle[{"i2cget -y 1", chipAdr, r}]]; 
   ReadLine[process]);
rPut[r_, d_] := WriteLine[process, StringRiffle[{"i2cset -y 1", chipAdr, r, d}]]; 

(* Get unSigned and Short Integer *)
	usGet[reg1_, reg2_] := (
	   	r = Flatten[{rGet[reg1], rGet[reg2]}];
 	  	r1 = Map[FromDigits[#, 16] &, StringReplace[r, "0x" -> ""]];
	   	BitShiftLeft[r1[[1]], 8] + r1[[2]]
   );

(* Get Signed Short Integer *)
ssGet[reg1_, reg2_] := (
   r = Flatten[{rGet[reg1], rGet[reg2]}];
   r1 = Map[FromDigits[#, 16] &, StringReplace[r, "0x" -> ""]];
   r2 = BitShiftLeft[r1[[1]], 8] + r1[[2]];
   If[r2 > 32767, -32768 + (r2 - 32768), r2]
   );
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* LSM303DLHC magneto meter *)
(* set data rate 30Hz *)
rPut["0x00", "0x14"];
(*  continuous conversion *)
rPut["0x02", "0x00"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read LSM303DLHC magneto meter *)
{ssGet["0x03", "0x04"], ssGet["0x05", "0x06"], ssGet["0x07", "0x08"]}
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read and plot LSM303DLHC magneto meter Z *)
d = Table[{ssGet["0x03", "0x04"], ssGet["0x05", "0x06"], ssGet["0x07", "0x08"]}, {20}];
ListLinePlot[d[[All, 1]]]
------------------------------------------------------------------------------------------------------------------------------------
A7.1 Dovewill (Adafruit) 10 DOF  6軸と方位と温度・気圧モジュール:3G4250D ジャイロスコープ
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read A3G4250D gyroscope *)
chipAdr = "0x69";
process = StartProcess[$SystemShell];
rGet[reg_] := StringTrim[RunProcess[{"i2cget", "-y", "1", chipAdr, reg}, "StandardOutput"]];
rGet["0x0f"](* datasheet shows Who_am _I register 0x0f value is 0xd3 *)
------------------------------------------------------------------------------------------------------------------------------------
7.1 Dovewill (Adafruit) 10 DOF  6軸と方位と温度・気圧モジュール:BMP180 温度・気圧センサー
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* initialize BMP180 *)
chipAdr = "0x77";
process = StartProcess[$SystemShell];
ac1 = ssGet["0xaa", "0xab"];
ac2 = ssGet["0xac", "0xad"];
ac3 = ssGet["0xae", "0xaf"];
ac4 = usGet["0xb0", "0xb1"];
ac5 = usGet["0xb2", "0xb3"];
ac6 = usGet["0xb4", "0xb5"];
b1 = ssGet["0xb6", "0xb7"];
b2 = ssGet["0xb8", "0xb9"];
mb = ssGet["0xba", "0xbb"];
mc = ssGet["0xbc", "0xbd"];
md = ssGet["0xbe", "0xbf"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* convert to temp. BMP180 *)
rPut["0xf4", "0x2e"]; 
Pause[0.05];
ut = usGet["0xf6", "0xf7"];
x1 = (ut - ac6)*ac5/2.^15;
x2 = mc*2.^11/(x1 + md);
b5 = x1 + x2;
t = (b5 + 8.)/2.^4/10.
------------------------------------------------------------------------------------------------------------------------------------
7.2 GY-511 LSM303DLHC 3軸と方位モジュール:LSM303DLHC 加速度計
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* initialize LSM303DLHC accelerometer *)
chipAdr = "0x19";
process = StartProcess[$SystemShell];
rGet[r_] := (
   WriteLine[process, StringRiffle[{"i2cget -y 1", chipAdr, r}]]; 
   ReadLine[process]
   );
rPut[r_, d_] := WriteLine[process, StringRiffle[{"i2cset -y 1", chipAdr, r, d}]]; 
(* Get Signed Short Integer *)
ssGet[{reg1_, reg2_}] := (
   r = Flatten[{rGet[reg1], rGet[reg2]}];
   r1 = Map[FromDigits[#, 16] &, StringReplace[r, "0x" -> ""]];
   r2 = BitShiftLeft[r1[[1]], 8] + r1[[2]];
   If[r2 > 32767, -32768 + (r2 - 32768), r2]
   );
areg = Association[cntlReg1 -> "0x20", mrReg -> "0x02",
   outXA -> {"0x29", "0x28"}, outYA -> {"0x2b", "0x2a"}, outZA -> {"0x2d", "0x2c"}];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* LSM303DLHC accelerometer *)
(* set output data rate to 50Hz *)
rPut[areg@cntlReg1, "0x47"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read LSM303DLHC accelerometer *)
{ssGet[areg@outXA], ssGet[areg@outYA], ssGet[areg@outZA]}
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* 100 read LSM303DLHC accelerometer *)
Timing[d = Table[{ssGet[areg@outXA], ssGet[areg@outYA], ssGet[areg@outZA]}, {100}];]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* plot data LSM303DLHC accelerometer *)
ListLinePlot[d[[All, 3]]]
------------------------------------------------------------------------------------------------------------------------------------
7.2 GY-511 LSM303DLHC 3軸と方位モジュール:LSM303DLHC 磁場センサ
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* initialize LSM303DLHC magnetic sensor *)
chipAdr = "0x1e";
process = StartProcess[$SystemShell];
rGet[r_] := (
   WriteLine[process, StringRiffle[{"i2cget -y 1", chipAdr, r}]]; 
   ReadLine[process]
   );
rPut[r_, d_] := WriteLine[process, StringRiffle[{"i2cset -y 1", chipAdr, r, d}]]; 
(* Get Signed Short Integer *)
ssGet[{reg1_, reg2_}] := (
   r = Flatten[{rGet[reg1], rGet[reg2]}];
   r1 = Map[FromDigits[#, 16] &, StringReplace[r, "0x" -> ""]];
   r2 = BitShiftLeft[r1[[1]], 8] + r1[[2]];
   If[r2 > 32767, -32768 + (r2 - 32768), r2]
   );
mreg = Association[
   craReg -> "0x00", mrReg -> "0x02",
   outXM -> {"0x03", "0x04"}, outYM -> {"0x07", "0x08"}, outZM -> {"0x05", "0x06"}, tmp -> {"0x31", "0x32"}
   ];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* TEMP enable and data rate 30Hz *)
rPut[mreg@craReg, "0x94"];
(* continuous conversion *)
rPut[mreg@mrReg, "0x00"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read LSM303DLHC magnetic sensor *)
{ssGet[mreg@tmp]/16., ssGet[mreg@outXM], ssGet[mreg@outYM], ssGet[mreg@outZM]}
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read LSM303DLHC magnetic sensor 100 data *)
Timing[d = Table[{ssGet[mreg@tmp]/16., ssGet[mreg@outXM], ssGet[mreg@outYM], ssGet[mreg@outZM]}, {100}];]
------------------------------------------------------------------------------------------------------------------------------------
7.3 GY-521 MPU-6050 6軸モジュール:MPU-6050のFIFO
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* initialize MPU6050 *)
chipAdr = "0x68";
(* control register address *)
reg = Association[ 
   "whoAmI" -> "0x75", "LPF" -> "0x1a", 
   "gyroConf" -> "0x1b", "accelConf" -> "0x1c", 
   "signalPathReset" -> "0x68", "powerManage1" -> "0x6b", "powerManage2" -> "0x6c"];
(* data register address *)
sreg = Association[
   "accelX0" -> "0x3b", "accelY0" -> "0x3d", "accelZ0" -> "0x3f",
   "tmp0" -> "0x41",
   "gyroX0" -> "0x43", "gyroY0" -> "0x45", "gyroZ0" -> "0x47"];
   
timeOut = 0.1;
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* MPU6050 controller *)
(* shell interface to i2c *)
rGet[r_] := (WriteLine[process, StringRiffle[{"i2cget -y 1", schipAdr, r}]];
   ReadLine[process, TimeConstraint -> timeOut]);
rGetW[r_] := (WriteLine[process, StringRiffle[{"i2cget -y 1", schipAdr, r, "w"}]];
   ReadLine[process, TimeConstraint -> timeOut]);
rPut[r_, d_] := WriteLine[process, StringRiffle[{"i2cset -y 1", schipAdr, r, d}]];
(* Get Signed Short Integer from a word *)
ssGet[r_] := (
   If[r == "0" || r == "" || StringLength[r] != 6, Return[rprev]];
      rprev = r; 
   r1 = StringTake[r, {5, 6}] <> StringTake[r, {3, 4}];
   r2 = FromDigits[r1, 16];
   If[# > 32767, -32768 + (# - 32768), #] &[r2]);
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* MPU6050 controller *)
(*  startup shell process *)
process = StartProcess[$SystemShell];
(*  power manage 1 set to 0 wakes up MPU6050 *)
rPut[reg["powerManage1"], "0x00"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* MPU6050 controller *)
(* WHO_AM _I will return 0x68 or 0x72 *)
rGet[reg["whoAmI"]]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* MPU6050 controller temperature *)
(* get temperature of die *)
rv = Map[rGetW, sreg];
ssGet[rv["tmp0"]]/340. + 36.53
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* MPU6050 controller plot graphe *)
d = Table[
   rv = Map[rGetW, sreg];
   ssGet[rv["accelZ0"]], {100}];
ListLinePlot[d]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* MPU6050 controller aliner *)
(* ... *)
aline = rGet[whoAmI];
If[aline != myCode, ReadString[process, EndOfBuffer]];
gyroYdata=ssGet[rGetW[sreg["gyroY0"]]]; (* reading example for gyro-Y direction *)
(* ... *)
------------------------------------------------------------------------------------------------------------------------------------
7.3 GY-521 MPU-6050 6軸モジュール:HC-SR04/US-015 超音波距離センサの仕様 
------------------------------------------------------------------------------------------------------------------------------------
// Arduino
// digikeyboard for ultra sonic sensor
# include "DigiKeyboard.h"
# define echoPin 0 // PB0
# define trigPin 2 // PB2
 
unsigned int duration; 
void setup () {
  pinMode ( echoPin, INPUT );
  pinMode ( trigPin, OUTPUT );
  }

void loop () {
    DigiKeyboard.sendKeyStroke (0);
         
       digitalWrite (trigPin, LOW); 
       delayMicroseconds (2); 
       digitalWrite ( trigPin, HIGH ); 
       delayMicroseconds ( 50 ); 
       digitalWrite ( trigPin, LOW );
       delayMicroseconds ( 50 ); 
        
       duration = pulseIn ( echoPin, HIGH, 100000 ); // observe pulse duration
    // distance[m] = duration[uS]/2.*.00035[m/uS]
      
    DigiKeyboard.println ("duration");
    DigiKeyboard.delay (200);
  
    DigiKeyboard.println (duration);
    DigiKeyboard.delay (200);
  
    delay (1000);
  }
------------------------------------------------------------------------------------------------------------------------------------
7.3 GY-521 MPU-6050 6軸モジュール:Raspberry PiにI2C接続したATtiny超音波センサプログラム
------------------------------------------------------------------------------------------------------------------------------------
// Arduino
// controller for ultra sonic sensor
#include "TinyWireS.h"  // I2C routines

#define echoPin 3 // PB3
#define trigPin 4 // PB4
#define LED_PIN 1 // PB1
             //  SDA PB0
              // SCL PB2
#define I2C_SLAVE _ADDRESS 0x5A // the 7-bit address
#ifndef TWI_RX _BUFFER _SIZE
#define TWI_RX _BUFFER _SIZE ( 16 )
#endif
//
 
unsigned long duration;
unsigned long interval = 60; 
int ledState = 0;
unsigned long previousMillis = 0;
unsigned long currentMillis= 0;

volatile uint8_t i2c_regs[] =
{   0xDE,   // initial value of registers
    0xAD, 
    0xBE, 
    0xEF, 
};

volatile byte reg_position;
const byte reg_size = sizeof(i2c_regs);

void requestEvent()
{  reg_position %= reg_size;
    TinyWireS.send(i2c_regs[reg_position]);
    reg_position++;
}

void receiveEvent(uint8_t howMany)
{   // Sanity check
    if ((howMany < 1) || (howMany > TWI_RX _BUFFER _SIZE)) return;
    
    reg_position = TinyWireS.receive();
    howMany--;

    while(howMany--)
    {
        reg_position %= reg_size;
        i2c_regs[reg_position] = TinyWireS.receive();
        reg_position++;
    }
}

void setup()
{   pinMode( echoPin, INPUT );
    pinMode( trigPin, OUTPUT );
    pinMode( LED_PIN,OUTPUT );
    mt08Blink(LED_PIN, 2);               //LED blink 2-times following bootup

    TinyWireS.begin(I2C_SLAVE _ADDRESS);
    TinyWireS.onReceive(receiveEvent);
    TinyWireS.onRequest(requestEvent);
}

void loop()
{  TinyWireS_stop _check();
   //   
   currentMillis= millis(); // get time in milli second
   digitalWrite( trigPin, HIGH ); 
   delayMicroseconds( 50 );
   digitalWrite( trigPin, LOW );    
   duration = pulseIn( echoPin, HIGH ); // count pulse duration with micro second
   while((currentMillis - previousMillis) <= interval){
    currentMillis=millis();
   }  //wait loop for detector analog delay
   previousMillis = currentMillis;
   i2c_regs[0]= duration & 0xff;; // set data of register0 changed through I2C
   i2c_regs[1]= (duration>>8) & 0xff;
}

void mt08Blink(byte led, byte times)
{ times *= 2;
  while(times > 0) {
    digitalWrite(led,(times & 0x01) ? LOW : HIGH);
    tws_delay (200);
    times--;
  }
}
------------------------------------------------------------------------------------------------------------------------------------
7.3 GY-521 MPU-6050 6軸モジュール:Raspberry Pi ZeroとATtiny85の接続
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* start process *)
chipAdr ="0x5a";
reg = Association[lb ->"0x00", hb ->"0x01"];
process = StartProcess[$SystemShell];
rGet[r_]:= (
   WriteLine[process, StringRiffle[{"i2cget -y 1", chipAdr, r}]];
   ReadLine[process]);
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* distance[m]=duration[uS]/2.*.00035[m/uS] *)
r = {rGet[reg[Ab]], rGet[reg[lb]]};
r1 = Map[FromDigits[#, 16] &, StringReplace[r, "0x"->""]];
r2 = (BitShiftLeft[r1[[1]], 8] + r1[[2]])*0.5*.00035
------------------------------------------------------------------------------------------------------------------------------------
8.1 ST7032 LCD
------------------------------------------------------------------------------------------------------------------------------------
# bash
# initialize display
i2cset -y 1 0x3e 0x00 0x38 0x39 0x14 0x70 0x56 0x6c i
i2cset -y 1 0x3e 0x00 0x38 0x0c 0x01 i
------------------------------------------------------------------------------------------------------------------------------------
8.1 ST7032 LCD:関数の準備
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* prepare function for LCD display  *)
process=StartProcess[$SystemShell];
getStr:=(
 Pause[0.01];
 StringCases[ReadLine[process],"="~~x__->x]
);

chipAdr="0x3e";
cmd="0x00";
data="0x40";

putComd[str_]:=WriteLine[process,StringRiffle[{"i2cset -y 1",chipAdr,cmd,Apply[Sequence,str],"i"}]];

putLine[str_]:=(
 hexList=Map["0x"<>IntegerString[#,16]&,ToCharacterCode[StringPadRight[str,8]]];
 dataList=StringRiffle[{"i2cset -y 1",chipAdr,data,Apply[Sequence,hexList],"i"}];
 WriteLine[process,dataList];
);

putWindow[str1_,str2_]:=(
 putComd["0x80"];
 putLine[str1];
 putComd["0xc0"];
 putLine[str2];
);
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(*  initialize LCD display  *)
putComd[{"0x38","0x39","0x14","0x70","0x56","0x6c"}];
Pause[0.2];
putComd[{"0x38" ,"0x0c","0x01"}];
------------------------------------------------------------------------------------------------------------------------------------
(*  Mathematica  *)
(*  show vcgencmd data to LCD display  *)
Do[
 WriteLine[process, "vcgencmd measure_temp"];
 putWindow["cpu temp", getStr[[1]]];
 Pause[1.5];
 WriteLine[process, "vcgencmd get_mem arm"];
 putWindow["mem arm", getStr[[1]]];
 Pause[1.5];
 WriteLine[process, "vcgencmd measure_clock arm"];
 clkstr = StringDrop[getStr, -6] <> " MHz";
 putWindow["clk arm", clkstr];
 Pause[1.5];
 , {10}]
------------------------------------------------------------------------------------------------------------------------------------
8.2 SSD1306 OLED
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* dot-image viewer *)
s="{pqrXYZ";
s1=Flatten@Map[fontTable[#]&,Characters[s]];
s2=Map[StringReplace[#,"0x"->""]&,s1];
s3=Map[PadLeft[IntegerDigits[FromDigits[#,16],2],8]&,s2];
s4=s3/.{1->Graphics[Disk[]],0->Graphics[Circle[]]};
GraphicsGrid[Transpose@s4,Frame->True]
------------------------------------------------------------------------------------------------------------------------------------
8.2 SSD1306 OLED:イメージテーブルの準備
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* SSD1306 image table *)
fontTable = Association[
   " " -> {"0x00", "0x00", "0x00"}, 
   "!" -> {"0x00", "0x7c", "0x00", "0x00"}, 
   "\"" -> {"0x00", "0x60", "0x60", "0x00", "0x00", "0x00"}, 
   "#" -> {"0x00", "0x3c", "0x68", "0x7c", "0x28", "0x00", "0x00"}, 
   "$" -> {"0x14", "0x2c", "0x7e", "0x2c", "0x00", "0x00"}, 
   "%" -> {"0x00", "0x64", "0x50", "0x78", "0x2c", "0x14", "0x4c", "0x00", "0x00", "0x00"}, 
   "&" -> {"0x00", "0x18", "0x64", "0x54", "0xc", "0x1c", "0x00", "0x00"}, 
   "'" -> {"0x00", "0x60", "0x00", "0x00", "0x00"}, 
   "(" -> {"0x00", "0x3c", "0x42", "0x00", "0x00"}, 
   ")" -> {"0x42", "0x3c", "0x00", "0x00"}, 
   "*" -> {"0x00", "0x38", "0x38", "0x38", "0x00", "0x00"}, 
   "+" -> {"0x00", "0x10", "0x10", "0x3c", "0x10", "0x10", "0x00", "0x00", "0x00"}, 
   "," -> {"0x00", "0x6", "0x00", "0x00"}, 
   "-" -> {"0x8", "0x8", "0x00", "0x00"}, 
   "." -> {"0x00", "0x4", "0x00", "0x00"}, 
   "/" -> {"0xe", "0x70", "0x00"}, 
   "0" -> {"0x38", "0x44", "0x44", "0x38", "0x00"}, 
   "1" -> {"0x00", "0x44", "0x7c", "0x4", "0x00"}, 
   "2" -> {"0x4", "0x4c", "0x54", "0x64", "0x00", "0x00"}, 
   "3" -> {"0x44", "0x54", "0x54", "0x6c", "0x00", "0x00"}, 
   "4" -> {"0x8", "0x38", "0x48", "0x7c", "0x8", "0x00"}, 
   "5" -> {"0x00", "0x64", "0x64", "0x1c", "0x00", "0x00"}, 
   "6" -> {"0x38", "0x64", "0x64", "0x58", "0x00", "0x00"}, 
   "7" -> {"0x00", "0x44", "0x58", "0x60", "0x00", "0x00"}, 
   "8" -> {"0x6c", "0x54", "0x6c", "0x00", "0x00", "0x00"}, 
   "9" -> {"0x64", "0x54", "0x54", "0x38", "0x00", "0x00"}, 
   ":" -> {"0x00", "0x24", "0x00"}, 
   ";" -> {"0x00", "0x26", "0x00", "0x00"}, 
   "<" -> {"0x00", "0x10", "0x18", "0x18", "0x24", "0x4", "0x00", "0x00"}, 
   "=" -> {"0x00", "0x18", "0x18", "0x18", "0x18", "0x00", "0x00"}, 
   ">" -> {"0x00", "0x24", "0x28", "0x18", "0x10", "0x10", "0x00", "0x00"}, 
   "?" -> {"0x40", "0x5c", "0x60", "0x00", "0x00"}, 
   "@" -> {"0x00", "0x38", "0x54", "0xaa", "0xaa", "0x78", "0x70", "0x00", "0x00", "0x00"}, 
   "A" -> {"0x4", "0x38", "0x68", "0x18", "0x4", "0x00"}, 
   "B" -> {"0x7c", "0x54", "0x54", "0x6c", "0x00"}, 
   "C" -> {"0x38", "0x44", "0x44", "0x44", "0x00", "0x00"}, 
   "D" -> {"0x7c", "0x44", "0x44", "0x38", "0x00"}, 
   "E" -> {"0x7c", "0x54", "0x54", "0x44", "0x00"}, 
   "F" -> {"0x7c", "0x50", "0x50", "0x00", "0x00"}, 
   "G" -> {"0x38", "0x44", "0x44", "0x54", "0x5c", "0x00"}, 
   "H" -> {"0x7c", "0x10", "0x10", "0x7c", "0x00"}, 
   "I" -> {"0x7c", "0x00", "0x00"}, "J" -> {"0x00", "0x2", "0x7e", "0x00"}, 
   "K" -> {"0x7c", "0x10", "0x28", "0x44", "0x00", "0x00"}, 
   "L" -> {"0x7c", "0x4", "0x4", "0x00", "0x00"}, 
   "M" -> {"0x7c", "0x70", "0x18", "0x60", "0x7c", "0x00"}, 
   "N" -> {"0x7c", "0x30", "0x8", "0x7c", "0x00"}, 
   "O" -> {"0x38", "0x44", "0x44", "0x44", "0x38", "0x00"}, 
   "P" -> {"0x7c", "0x50", "0x60", "0x00"}, 
   "Q" -> {"0x38", "0x44", "0x44", "0x46", "0x38", "0x00"}, 
   "R" -> {"0x7c", "0x50", "0x6c", "0x00", "0x00"}, 
   "S" -> {"0x64", "0x54", "0x54", "0x4c", "0x00"}, 
   "T" -> {"0x40", "0x40", "0x7c", "0x40", "0x40", "0x00"}, 
   "U" -> {"0x7c", "0x4", "0x4", "0x7c", "0x00"}, 
   "V" -> {"0x60", "0x18", "0xc", "0x30", "0x40", "0x00"}, 
   "W" -> {"0x60", "0x1c", "0x3c", "0x70", "0xc", "0x3c", "0x40", "0x00"}, 
   "X" -> {"0x4", "0x68", "0x30", "0x4c", "0x00", "0x00"}, 
   "Y" -> {"0x40", "0x20", "0x1c", "0x60", "0x00", "0x00"}, 
   "Z" -> {"0x44", "0x5c", "0x64", "0x44", "0x00", "0x00"}, 
   "[" -> {"0x00", "0x7f", "0x41", "0x00", "0x00", "0x00"}, 
   "\\" -> {"0x70", "0xe", "0x00"}, 
   "]" -> {"0x41", "0x7f", "0x00", "0x00"}, 
   "^" -> {"0x00", "0x20", "0x40", "0x40", "0x20", "0x00", "0x00"}, 
   "_" -> {"0x00", "0x2", "0x2", "0x2", "0x2"}, 
   "`" -> {"0x00", "0x40", "0x00", "0x00", "0x00"}, 
   "a" -> {"0x2c", "0x34", "0x3c", "0x00", "0x00"}, 
   "b" -> {"0x7c", "0x24", "0x24", "0x18", "0x00"}, 
   "c" -> {"0x18", "0x24", "0x24", "0x00", "0x00"}, 
   "d" -> {"0x18", "0x24", "0x24", "0x7c", "0x00"}, 
   "e" -> {"0x18", "0x34", "0x34", "0x10", "0x00"}, 
   "f" -> {"0x20", "0x7c", "0x60", "0x00"}, 
   "g" -> {"0x18", "0x26", "0x26", "0x3e", "0x00", "0x00"}, 
   "h" -> {"0x7c", "0x20", "0x3c", "0x00"}, 
   "i" -> {"0x5c", "0x00"}, 
   "j" -> {"0x2", "0x7e", "0x00", "0x00"}, 
   "k" -> {"0x7c", "0x18", "0x24", "0x00", "0x00"}, 
   "l" -> {"0x7c", "0x04", "0x00"}, 
   "m" -> {"0x3c", "0x20", "0x3c", "0x20", "0x3c", "0x00", "0x00"}, 
   "n" -> {"0x3c", "0x20", "0x3c", "0x00"}, 
   "o" -> {"0x18", "0x24", "0x24", "0x18", "0x00"}, 
   "p" -> {"0x3e", "0x24", "0x24", "0x18", "0x00"}, 
   "q" -> {"0x18", "0x24", "0x24", "0x3e", "0x00"}, 
   "r" -> {"0x3c", "0x20", "0x20", "0x00"}, 
   "s" -> {"0x00", "0x34", "0x2c", "0x2c", "0x00"}, 
   "t" -> {"0x00", "0x7c", "0x24", "0x00"}, 
   "u" -> {"0x3c", "0x4", "0x3c", "0x00", "0x00"}, 
   "v" -> {"0x30", "0xc", "0x1c", "0x20", "0x00"}, 
   "w" -> {"0x30", "0xc", "0x30", "0x18", "0x3c", "0x00", "0x00"}, 
   "x" -> {"0x24", "0x18", "0x38", "0x4", "0x00"}, 
   "y" -> {"0x20", "0x1e", "0x18", "0x20", "0x00"}, 
   "z" -> {"0x2c", "0x34", "0x24", "0x00", "0x00", "0x00"}, 
   "{" -> {"0x00", "0x8", "0x77", "0x41", "0x00", "0x00"}, 
   "|" -> {"0x00", "0x7f", "0x00", "0x00", "0x00"}, 
   "}" -> {"0x00", "0x41", "0x77", "0x8", "0x00", "0x00"}];

------------------------------------------------------------------------------------------------------------------------------------
8.2 SSD1306 OLED:SSD1306に表示してみる
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* output to display SSD1306 *)
chipAdr = "0x3c";

cmdStr := {"i2cset -y 1", chipAdr, "0x00"};(* command string is indexed by 0x00 *)
dataStr := {"i2cset -y 1", chipAdr, "0x40"};(* data string is indexed by 0x40 *)

rPut[r_] := WriteLine[process, StringRiffle[Join[cmdStr, {r}]]];(* register setup process *)

setCursor[r_] := (
   rPut[StringJoin["0xb", ToString[r]]];(* setup cursor *)
   rPut["0x10"]; rPut["0x02"](* 10: set higher nible is 0, 02: set lower nible to 2*));

clrLine[r_] := (
   blnkStr = Join[dataStr, ConstantArray["0x00", 32], {"i"}];(* output buffer length is 32 *)
   setCursor[r];
   Table[WriteLine[process, StringRiffle[blnkStr]], {4}]);(* one line is composed of 32*4 *)

clrScreen := Table[clrLine[i], {i, 7, 0, -1}];(* clear 7 lines *)

dispLine[r_, str_] := (
   clrLine[r];(* dispplay a line on r-line *)
   setCursor[r];
   cstr = Map[fontTable, Characters[str]];(* convert string to bitmap *)
   dcom = Map[StringRiffle[Join[dataStr, #, {"i"}]] &, cstr];
   Map[WriteLine[process, #] &, dcom]);

(* start display *)
process = StartProcess[$SystemShell];

rPut["0x8d"];(*8d:charge pump on*)
rPut["0x14"];(*14:enable charge pump*)
rPut["0xaf"];(*af:display on in normal mode*)
rPut["0xa1"];(*a1:set segment remap to reverse*)
clrScreen;

dispLine[7, "SSD1306 is a single-chip"];
dispLine[6, "CMOS OLED/PLED driver with"];
dispLine[5, "controller for"];
dispLine[4, "organic/polymer display"];
------------------------------------------------------------------------------------------------------------------------------------
8.3 プロポーショナルドットイメージの生成:ビットマップフォントの調整
------------------------------------------------------------------------------------------------------------------------------------
In[46]:= (* Mathematica *)
(* chatacter " shoud be changed to escaped style \" *)
a0 = "0x00, //''
  0x49,0x24, //'!'
  0xF0, //'\"'
  	0x31,0xE5,0x1E,0x50, // '#'
  	0x27,0xA7,0xF2,0x00, // '$'
  	0xE2,0xC6,0x8D,0x14, // '%'
  	0x61,0x0A,0xA6,0x78, // '&'
  	0xC0, // '''
  	0x6A,0xA0, // '('
  	0x95,0x60, // ')'
  	0x21,0x08,0x00, // '*'
  	0x01,0x3E,0x42,0x00, // '+'
  	0x50, // ','
  	0xC0, // '-'
  	0x40, // '.'
  	0x49,0x49,0x00, // '/'
  	0x69,0x99,0x60, // '0'
  	0x61,0x08,0x47,0x00, // '1'
  	0x70,0x88,0x8F,0x00, // '2'
  	0xF1,0x61,0xF0, // '3'
  	0x32,0x95,0xF1,0x00, // '4'
  	0x66,0x11,0x70, // '5'
  	0x7E,0x99,0x60, // '6'
  	0x71,0x22,0x40, // '7'
  	0xF5,0x5E, // '8'
  	0xE9,0x71,0xE0, // '9'
  	0x41, // ':'
  	0x41,0x40, // ';'
  	0x00,0xB8,0xC1,0x80, // '<'
  	0x79,0xE0, // '='
  	0x06,0x0E,0xC8,0x00, // '>'
  	0xE5,0x24, // '?'
  	0x31,0x3B,0xF3,0xB9,0x03,0x00, // '@'
  	0x23,0x14,0xE8,0x80, // 'A'
  	0xF9,0xE9,0xF0, // 'B'
  	0x74,0x21,0x07,0x00, // 'C'
  	0xE9,0x99,0xE0, // 'D'
  	0xF8,0xE8,0xF0, // 'E'
  	0xE8,0xE8,0x80, // 'F'
  	0x7C,0x27,0x17,0x80, // 'G'
  	0x99,0xF9,0x90, // 'H'
  	0xF8, // 'I'
  	0x24,0x92,0xC0, // 'J'
  	0x95,0x31,0x49,0x00, // 'K'
  	0x88,0x88,0xE0, // 'L'
  	0xDE,0xFB,0x58,0x80, // 'M'
  	0x9D,0xDB,0x90, // 'N'
  	0x74,0x63,0x17,0x00, // 'O'
  	0xF7,0x48, // 'P'
  	0x74,0x63,0x17,0x08, // 'Q'
  	0xEA,0xCA,0xA0, // 'R'
  	0xF8,0x61,0xF0, // 'S'
  	0xF9,0x08,0x42,0x00, // 'T'
  	0x99,0x99,0xF0, // 'U'
  	0x8C,0x94,0xC2,0x00, // 'V'
  	0x93,0x69,0xD3,0x66,0xC0, // 'W'
  	0x53,0x08,0xA9,0x00, // 'X'
  	0x92,0x88,0x42,0x00, // 'Y'
  	0xF1,0x10,0x8F,0x00, // 'Z'
  	0xEA,0xAC, // '['
  	0x92,0x24,0x80, // '\'
  	0xD5,0x5C, // ']'
  	0x31,0x20, // '^'
  	0x78, // '_'
  	0x08, // '`'
  	0xEE,0xF0, // 'a'
  	0x8E,0x99,0xE0, // 'b'
  	0x68,0x86, // 'c'
  	0x17,0x99,0x70, // 'd'
  	0x6F,0x86, // 'e'
  	0x6E,0x44,0x40, // 'f'
  	0x79,0x97,0x70, // 'g'
  	0x9E,0xDA, // 'h'
  	0xF8, // 'i'
  	0x55,0x70, // 'j'
  	0x8A,0xCC,0xA0, // 'k'
  	0xF8, // 'l'
  	0xFD,0x6B,0x50, // 'm'
  	0xF6,0xD0, // 'n'
  	0x69,0x96, // 'o'
  	0xE9,0x9E,0x80, // 'p'
  	0x79,0x97,0x10, // 'q'
  	0x1E,0x48, // 'r'
  	0x74,0x37, // 's'
  	0x46,0x44,0x60, // 't'
  	0x16,0xDE, // 'u'
  	0x9A,0x66, // 'v'
  	0xAA,0xE5,0x92, // 'w'
  	0xA6,0x69, // 'x'
  	0x96,0x64,0x40, // 'y'
  	0xEA,0x70, // 'z'
  	0x32,0x24,0x22,0x30, // '{'
  	0xFE, // '|'
  	0x61,0x08,0x22,0x11,0x80 // '}'
  ";
------------------------------------------------------------------------------------------------------------------------------------
(* setup SG90 function *)
(* set b0 character position and interval space *)
b0 = "{{0,1,1,3,0,0}, //''
  {1,3,5,4,0,-5}, //'!'
  {3,2,2,5,1,-5}, //'\"'
  	  { 4,   6,   5,   7,    0,   -5 }, // '#'
  	  { 8,   4,   7,   6,    0,   -5 }, // '$'
  	  { 12,   6,   5,   9,    1,   -5 }, // '%'
  	  { 16,   6,   5,   7,    1,   -5 }, // '&'
  	  { 20,   1,   2,   4,    1,   -5 }, // '''
  	  { 21,   2,   7,   4,    1,   -5 }, // '('
  	  { 23,   2,   7,   4,    0,   -5 }, // ')'
  	  { 25,   5,   4,   6,    0,   -5 }, // '*'
  	  { 28,   5,   5,   8,    1,   -5 }, // '+'
  	  { 32,   2,   2,   4,    0,   -1 }, // ','
  	  { 33,   3,   1,   4,    0,   -2 }, // '-'
  	  { 34,   2,   1,   3,    0,   -1 }, // '.'
  	  { 35,   3,   6,   3,    0,   -5 }, // '/'
  	  { 38,   4,   5,   7,    1,   -5 }, // '0'
  	  { 41,   5,   5,   6,    0,   -5 }, // '1'
  	  { 45,   5,   5,   6,    0,   -5 }, // '2'
  	  { 49,   4,   5,   6,    0,   -5 }, // '3'
  	  { 52,   5,   5,   6,    0,   -5 }, // '4'
  	  { 56,   4,   5,   6,    0,   -5 }, // '5'
  	  { 59,   4,   5,   7,    1,   -5 }, // '6'
  	  { 62,   4,   5,   5,    0,   -5 }, // '7'
  	  { 65,   3,   5,   6,    1,   -5 }, // '8'
  	  { 67,   4,   5,   7,    1,   -5 }, // '9'
  	  { 70,   2,   4,   3,    0,   -4 }, // ':'
  	  { 71,   2,   5,   4,    0,   -4 }, // ';'
  	  { 73,   5,   5,   7,    1,   -5 }, // '<'
  	  { 77,   6,   2,   7,    0,   -3 }, // '='
  	  { 79,   5,   5,   7,    1,   -5 }, // '>'
  	  { 83,   3,   5,   5,    0,   -5 }, // '?'
  	  { 85,   6,   7,   9,    1,   -6 }, // '@'
  	  { 91,   5,   5,   6,    0,   -5 }, // 'A'
  	  { 95,   4,   5,   7,    1,   -5 }, // 'B'
  	  { 98,   5,   5,   7,    1,   -5 }, // 'C'
  	  {102,   4,   5,   7,    1,   -5 }, // 'D'
  	  {105,   4,   5,   6,    1,   -5 }, // 'E'
  	  {108,   4,   5,   6,    1,   -5 }, // 'F'
  	  {111,   5,   5,   8,    1,   -5 }, // 'G'
  	  {115,   4,   5,   7,    1,   -5 }, // 'H'
  	  {118,   1,   5,   4,    1,   -5 }, // 'I'
  	  {119,   3,   6,   4,   -1,   -5 }, // 'J'
  	  {122,   5,   5,   6,    1,   -5 }, // 'K'
  	  {126,   4,   5,   6,    1,   -5 }, // 'L'
  	  {129,   5,   5,   8,    1,   -5 }, // 'M'
  	  {133,   4,   5,   7,    1,   -5 }, // 'N'
  	  {136,   5,   5,   8,    1,   -5 }, // 'O'
  	  {140,   3,   5,   6,    1,   -5 }, // 'P'
  	  {142,   5,   6,   8,    1,   -5 }, // 'Q'
  	  {146,   4,   5,   6,    1,   -5 }, // 'R'
  	  {149,   4,   5,   7,    1,   -5 }, // 'S'
  	  {152,   5,   5,   6,    0,   -5 }, // 'T'
  	  {156,   4,   5,   7,    1,   -5 }, // 'U'
  	  {159,   5,   5,   6,    0,   -5 }, // 'V'
  	  {163,   7,   5,   8,    0,   -5 }, // 'W'
  	  {168,   5,   5,   6,    0,   -5 }, // 'X'
  	  {172,   5,   5,   6,    0,   -5 }, // 'Y'
  	  {176,   5,   5,   7,    1,   -5 }, // 'Z'
  	  {180,   2,   7,   5,    1,   -5 }, // '['
  	  {182,   3,   6,   3,    0,   -5 }, // '\'
  	  {185,   2,   7,   4,    0,   -5 }, // ']'
  	  {187,   6,   2,   7,    0,   -5 }, // '^'
  	  {189,   5,   1,   5,   -1,    1 }, // '_'
  	  {190,   3,   2,   5,    0,   -6 }, // '`'
  	  {191,   3,   4,   6,    1,   -4 }, // 'a'
  	  {193,   4,   5,   7,    1,   -5 }, // 'b'
  	  {196,   4,   4,   6,    1,   -4 }, // 'c'
  	  {198,   4,   5,   7,    1,   -5 }, // 'd'
  	  {201,   4,   4,   6,    1,   -4 }, // 'e'
  	  {203,   4,   5,   4,    0,   -5 }, // 'f'
  	  {206,   4,   5,   7,    1,   -4 }, // 'g'
  	  {209,   3,   5,   6,    1,   -5 }, // 'h'
  	  {211,   1,   5,   4,    1,   -5 }, // 'i'
  	  {212,   2,   6,   4,    0,   -5 }, // 'j'
  	  {214,   4,   5,   6,    1,   -5 }, // 'k'
  	  {217,   1,   5,   4,    1,   -5 }, // 'l'
  	  {218,   5,   4,   8,    1,   -4 }, // 'm'
  	  {221,   3,   4,   6,    1,   -4 }, // 'n'
  	  {223,   4,   4,   7,    1,   -4 }, // 'o'
  	  {225,   4,   5,   7,    1,   -4 }, // 'p'
  	  {228,   4,   5,   7,    1,   -4 }, // 'q'
  	  {231,   3,   5,   5,    1,   -5 }, // 'r'
  	  {233,   4,   4,   6,    0,   -4 }, // 's'
  	  {235,   4,   5,   4,    0,   -5 }, // 't'
  	  {238,   3,   5,   6,    1,   -5 }, // 'u'
  	  {240,   4,   4,   5,    0,   -4 }, // 'v'
  	  {242,   6,   4,   7,    0,   -4 }, // 'w'
  	  {245,   4,   4,   5,    0,   -4 }, // 'x'
  	  {247,   4,   5,   5,    0,   -4 }, // 'y'
  	  {250,   3,   4,   6,    1,   -4 }, // 'z'
  	  {252,   4,   7,   6,    0,   -5 }, // '{'
  	  {256,   1,   8,   4,    1,   -5 }, // '|'
  	  {257,   5,   7,   6,    0,   -5 }  // '}'}
  ";
------------------------------------------------------------------------------------------------------------------------------------
8.3 プロポーショナルドットイメージの生成:メモリーイメージへの変換
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* preparing font bitmap *)
a1 = StringReplace[a0, Whitespace -> ""];
a2 = StringReplace[a1, "//''" -> ""];
a3 = StringReplace[a2, "//'" ~~ _ ~~ "'" -> ""];
a4 = StringReplace[a3, "'" -> ""];
a5 = StringReplace[a4, "0x" -> ""];
a = StringSplit[a5, ","];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* preparing font position parameter *)
b1 = StringReplace[b0, Whitespace -> ""];
b2 = StringReplace[b1, "//''" -> ""];
b3 = StringReplace[b2, "//'" ~~ _ ~~ "'" -> ""];
b4 = StringReplace[b3, "'" -> ""];
b = ToExpression[b4];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* get bitmap hex data series for each character *)
begin := b[[i, 1]] + 1;
end := b[[i + 1, 1]] /; i < 94;
end := Length[a] /; i == 94;
c = Table[Take[a, {begin, end}], {i, Length[b]}];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* combine to long binary before partitioning *)
binDigit = Map[Flatten, Table[Map[IntegerDigits[FromDigits[#, 16], 2, 8] &, c[[i]]], {i, Length[c]}]];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* getting font style parameters i=1:"space" to 94:"}" *)
i=1;
width = b[[i, 2]];
height = Min[7, b[[i, 3]]];
xAdvance = b[[i, 4]];
xOffset = b[[i, 5]];
yOffset = Min[b[[i, 6]], 0];

(* prepare pads *)
pad = ConstantArray[0, width];
bytePad = ConstantArray[0, 8];

(* set padding number *)
upPadding = 6 + yOffset;
downPadding = Max[8 - upPadding - height, 0];

(* raw font rectangle *)
rd = Take[Partition[binDigit[[i]], width], height];

(* padding rectangle *)
rt = Join[Table[pad, {upPadding}], rd, Table[pad, {downPadding}]];
rz = Join[Table[bytePad, {xOffset}], Transpose[rt](*,Table[bytePad,{xAdvance-width}]*)];

(*rrz=Map[Reverse,rz];*)
(* prepare form for downloading to SSD1306 *)
hex = IntegerString[Map[FromDigits[#, 2] &, rz], 16] /. "0" -> "00";
strSeries = StringReplace[ToString[Map[StringJoin["0x", #] &, hex]], {"," -> "", "{" -> "", "}" -> ""}];
Rule[FromCharacterCode[31 + i], strSeries]
------------------------------------------------------------------------------------------------------------------------------------
9.1 サーボモータ:SG90 サーボモータの使い方
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* setup SG90 function *)
process = StartProcess[$SystemShell];
(* setup SG90 servo motor *)
WriteLine[process, "gpio mode 1 pwm"];
WriteLine[process, "gpio pwm-ms"];
WriteLine[process, "gpio pwmc 192"]; (* set counter *)
WriteLine[process, "gpio pwmr 2000"];(* set resolution *)
WriteLine[process, "gpio pwm 1 60"];(* set to home position *)

clock := Do[WriteLine[process, "gpio pwm 1 " <> ToString[n]]; Pause[0.05], {n, 250, 60, -2}];
unclock := Do[WriteLine[process, "gpio pwm 1 " <> ToString[n]]; Pause[0.05], {n, 60, 250, 2}];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* SG90 continuous operation *)
While[True,
 unclock; Pause[1.0]; clock];
------------------------------------------------------------------------------------------------------------------------------------
9.1 サーボモータ:2個のSG90をMathematicaから制御する
------------------------------------------------------------------------------------------------------------------------------------
#!/bin/bash
# prepare script for PWM
cd /sys/class/pwm/pwmchip0
#
sudo sh -c "echo 0 > export"
cd pwm0
sudo chmod 666 period
sudo chmod 666 duty_cycle
sudo chmod 666 enable
#
cd ..
sudo sh -c "echo 1 > export"
cd pwm1
sudo chmod 666 period
sudo chmod 666 duty_cycle
sudo chmod 666 enable
#
cd ~
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* start process *)
process = StartProcess[$SystemShell, ProcessDirectory -> "/home/pi"];
WriteLine[process, "./pwminit"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* setup PWM0 *)
process0 = StartProcess[$SystemShell, ProcessDirectory -> "/sys/class/pwm/pwmchip0/pwm0"];
WriteLine[process0, "echo 20000000 > period"]; (* SG90 requires 50 Hz *)
WriteLine[process0, "echo 1450000 > duty_cycle"]; (* 1.45 ms set to position 0 deg *)
WriteLine[process0, "echo 1 > enable"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* setup PWM1 *)
process1 = StartProcess[$SystemShell, ProcessDirectory -> "/sys/class/pwm/pwmchip0/pwm1"];
WriteLine[process1, "echo 20000000 > period"];
WriteLine[process1, "echo 1450000 > duty_cycle"];
WriteLine[process1, "echo 1 > enable"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* read PWM condition *)
WriteLine[process0, "echo 2500000 > duty_cycle"]; 
WriteLine[process0, "cat duty_cycle"];
ReadLine[process0]
------------------------------------------------------------------------------------------------------------------------------------
9.1 サーボモータ:カメラマウントキットを使ったパンとチルトの同時制御
------------------------------------------------------------------------------------------------------------------------------------
#!/bin/bash
# double PWM enabler
cd /sys/class/pwm/pwmchip0
#
sudo sh -c "echo 0 > export"
cd pwm0
sudo chmod 666 period
sudo chmod 666 duty_cycle
sudo chmod 666 enable
echo 20000000 > period
echo 1480000 > duty_cycle
echo 1 > enable
#
cd ..
sudo sh -c "echo 1 > export"
cd pwm1
sudo chmod 666 period
sudo chmod 666 duty_cycle
sudo chmod 666 enable
echo 20000000 > period
echo 1350000 > duty_cycle
echo 1 > enable
#
cd ~
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* conical scan start process *)
process = StartProcess[$SystemShell, ProcessDirectory -> "/home/pi"];
WriteLine[process, "./pwminit"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* conical scan motor parameter *)
obj = {
   Association["axis" -> pan, 
    "register " -> "/sys/class/pwm/pwmchip0/pwm0", 
    "degduty" -> {{90, 570000}, {0, 1480000}, {-90, 2500000}}],
   Association["axis" -> tilt, 
    "register" -> "/sys/class/pwm/pwmchip0/pwm1", 
    "degduty" -> {{85, 530000}, {0, 1350000}, {-70, 2000000}}]};
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* conical scan define class *)
axis[name_[pdirectory_, ddPair_, x_]] := Module[
	{pwmCh = OpenWrite[pdirectory <> "/duty_cycle"], 
	est = Fit[ddPair, {1, x, x^2}, x], 
	init = 1400000, nStep = 20},
	
(*function to get last duty_cycle*)
	getDuty[name] ^:= init;
	
(*setDuty[name[Null]]^:=Null;*)
   setDuty[name[dc_]] ^:= Write[pwmCh, init = dc];
   
(*function get duty_cycle from angle*)
   getADuty[name[angle_]] ^:= Round[est /. x -> angle];
   
(*function from angle to move to destination*)
   getMove[name[angle_]] ^:= (previous = getDuty[name];
     new = getADuty[name[angle]];
     If[previous == new, Return[{}]];
     dutyList = Round[Range[previous, new, (new - previous)/nStep]])
   ];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* conical scan construct instance *)
Map[axis[#axis[#register, #degduty, dummy]] &, obj];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* conical scan function *)
move2[at_, ap_] := (
   tList = getMove[tilt[at]]; 
   pList = getMove[pan[ap]];
   Which[
   (Length[tList] == 0 && Length[pList] == 0), Null,
    Length[tList] == 0, Map[{setDuty[pan[#]];, Pause[0.01]} &, pList],
    Length[pList] == 0, Map[{setDuty[tilt[#]];, Pause[0.01]} &, tList],
    True, MapThread[{setDuty[tilt[#1]];, Pause[0.01], setDuty[pan[#2]];} &, {tList, pList}]
    ];
);
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* conical scan scan list *)
r= 15.0; 
nPoint= 8; 
tiltStartPos= 10;
panA= Round[r*Sin[Range[0, 2 Pi, Pi/nPoint]]];
tiltA= -r*Cos[Range[0, 2 Pi, Pi/nPoint]] + tiltStartPos;
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* conical scan 5 times *)
Do[Map[move2[#[[1]], #[[2]]] &, Transpose[{tiltA, panA}]], 5]
------------------------------------------------------------------------------------------------------------------------------------
9.2 ステッパモータ
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* stepper motor OOP style gpio definition *)
gpio[name_[n_]]:= Module[{process, gpn = n},
  
  (* each object has own shell process *)
  set[name] ^:= (process = StartProcess[$SystemShell];
    WriteLine[process, StringRiffle[{"gpio -g mode", gpn, "out"}]];);
  
  (* pause[] is for preventing writeline missing *)
  pulse[name] ^:= (WriteLine[process, StringRiffle[{"gpio -g write", gpn, "1"}]];
    Pause[0.01];
    WriteLine[process, StringRiffle[{"gpio -g write", gpn, "0"}]];
    Pause[0.01];);]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* stepper motor 1 *)
(* construct instances for each pin, and set to output mode *)
{gpio[p4[4]], gpio[p17[17]], gpio[p22[22]], gpio[p27[27]]};
{set[p4], set[p17], set[p22], set[p27]};

------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* stepper motor 2 *)
cw := {pulse[p4], pulse[p22], pulse[p27], pulse[p17]};
ccw := {pulse[p17], pulse[p27], pulse[p22], pulse[p4]};
Do[cw, {i, 64*8}]; Do[ccw, {i, 64*8}];
------------------------------------------------------------------------------------------------------------------------------------
9.4 DCモータドライバ
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* blush motor control prepare GPIO *)
	process = StartProcess[$SystemShell];
	WriteLine[process, "echo 17 > /sys/class/gpio/export"];
	WriteLine[process, "echo out > /sys/class/gpio/gpio17/direction"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* blush motor control prepare GPIO 1 *)
(* drive motor CCW *)
	WriteLine[process, "echo 1 > /sys/class/gpio/gpio17/value"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* blush motor control prepare GPIO 2 *)
(* drive motor CW *)

	WriteLine[process, "echo 0 > /sys/class/gpio/gpio17/value"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* blush motor control prepare GPIO 3 *)
	WriteLine[process, "sudo su -"];
	WriteLine[process, "cd /sys/class/pwm/pwmchip0"];
	WriteLine[process, "echo 0 > export"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* blush motor control PWM *)
	WriteLine[process, "echo 10000000 > pwm0/period"];(*setup 100 Hz*)
	WriteLine[process, "echo 2000000 > pwm0/duty_cycle"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* blush motor control 1 *)
(* drive motor 1 sec *)
	WriteLine[process, "echo 1 > pwm0/enable"]; Pause[1.0];
	WriteLine[process, "echo 0 > pwm0/enable"];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* blush motor control 2 *)
	chipAdr = "0x61";
	process = StartProcess[$SystemShell];
	rGet := (
     WriteLine[process, StringRiffle[{"i2cget -y 1", chipAdr, "0x01"}]]; 
     ReadLine[process]);
	rPut[d_] := WriteLine[process, StringRiffle[{"i2cset -y 1", chipAdr, "0x00", d}]]; 
	
	rPut["0x5e"]; Pause[0.1]; rPut["0x00"];
	rPut["0x5d"]; Pause[0.1]; rPut["0x00"];
------------------------------------------------------------------------------------------------------------------------------------
11.2 rpioによるGPIO制御:Node.jsのスクリプトでGPIOを制御してLEDを点滅させる
------------------------------------------------------------------------------------------------------------------------------------
// Node.js
// blink LED 1
var rpio= require ('rpio'); 
var LED_PIN _ 1= 13; // GPIO27
rpio.open(LED_PIN _ 1, rpio.OUTPUT, rpio.LOW);

for (var i= 0;  < 100; i++ ) {
  rpio.write(LED_PIN _ 1, rpio.HIGH);
   rpio.msleep(100);
   rpio.write(LED_PIN _ 1, rpio.LOW);
  rpio.msleep(100);
  }
------------------------------------------------------------------------------------------------------------------------------------
11.3 MathematicaとNode.jsとの接続
------------------------------------------------------------------------------------------------------------------------------------
// Node.js
// blink LED 2
var http = require (' http');
var url = require (' url');
var rpio = require (' rpio');

var Led = 13; // GPIO2
rpio.open (Led, rpio.OUTPUT, rpio.LOW);
var period = 100;
var isOn = false;
var blink;
//
   timer = {
       start : function (period) {
          blink = setInterval ( function () {
               if (isOn) {
                 rpio.open (Led, rpio.OUTPUT, rpio.LOW);
                 isOn = false;
                 }
                else {
                 rpio.open (Led, rpio.OUTPUT, rpio.HIGH);
                 isOn = true;
                 } 
              }, period);
         return blink;
         },
      
      change : function (newPeriod) {
         clearInterval (blink);
      
          blink = setInterval ( function () {
               if (isOn) {
                 rpio.open (Led, rpio.OUTPUT, rpio.LOW);
                 isOn = false;
                 }
                else {
                 rpio.open (Led, rpio.OUTPUT, rpio.HIGH);
                 isOn = true;
                 } 
              }, newPeriod);
         return blink   
        }
   };
//
   var blink = timer.start (period);

var server = http.createServer ();
server.on (' request', function (req, res) {
         var obj = url.parse (req.url, true).query;
         
             period = Number (obj.val); // get value of val parameter
              console.log (period); // val value
            var blink = timer.change (period);
     
         res.writeHead (200, {' Content - Type' : ' text/plain'});
         res.write (' period changed');
         res.end ();
     });
server.listen (3000);
------------------------------------------------------------------------------------------------------------------------------------
11.3 MathematicaとNode.jsとの接続
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* request to Node.js *)
req = HTTPRequest["localhost:3000"]
URLRead[req]
URLExecute[req, {"val" -> 1000, "opt" -> "good"}]
------------------------------------------------------------------------------------------------------------------------------------
12.4 オブジェクト指向プログラミング:クラスの定義
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* OOP class definition *)
class[nam_] := Module[{this = class, local = 0},
    localValueSetMethod[nam[x_]] ^:= local = x;
    localValueGetMethod[nam] ^:= local;
    ]
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* OOP instance construction *)
objectList = {instance1, instance2};
Map[class, objectList];
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* OOP method execution *)
{localValueSetMethod[instance1[1]], localValueSetMethod[instance2[2]]}
------------------------------------------------------------------------------------------------------------------------------------
12.5 二重振子のカオス発展を観察:オブジェクト指向スタイルによる二重振子の定義
------------------------------------------------------------------------------------------------------------------------------------
(* Mathematica *)
(* double pendulum specification *)
{g = 9.8, m = 1, r1 = 1, r2 = 0.5};

(* double pendulum class *)
PendulumClass[nam_] := Module[{θ1, θ2, ans, T1, T2, V1, V2, t, L, lkeq, initcond},
   
   initialize[nam[th1_, th2_]] ^:= (
     (* Lagrangian setup *)
     T1 = 1/2 m*r1^2*θ1'[t]^2;
     V1 = -m*g*r1*Cos[θ1[t]];
     T2 = 1/2 m*(r1^2*θ1'[t]^2 + r2^2*θ2'[t]^2 + 2 r1*r2*θ1'[t]*θ2'[t]*r1*r2*Cos[θ1[t] - θ2[t]]);
     V2 = -m*g*(r1*Cos[θ1[t]] + r2*Cos[θ2[t]]);
     L = T1 + T2 - (V1 + V2);
     
     (* Lagrange equation of motion *)
     lkeq = {D[D[L, θ1'[t]], t] - D[L, θ1[t]] == 0,
       D[D[L, θ2'[t]], t] - D[L, θ2[t]] == 0};
     initcond = {
       θ1[0] == th1,
       θ2[0] == th2,
       θ1'[0] == 0,
       θ2'[0] == 0};
     
     (* Numerical solve of equation *)
     ans = NDSolve[{lkeq, initcond}, {θ1, θ2}, {t, 0, time}, MaxSteps -> Infinity, PrecisionGoal -> ∞][[1]];
     );
   
   (* Pendulum graphics return *)
   pendulum[nam[tr_]] ^:= (
     Graphics[{Line[{{0, 0}, {r1*Sin[θ1[tr]], -r1*Cos[θ1[tr]]} /. ans}], Line[{{r1*Sin[θ1[tr]], -r1*Cos[θ1[tr]]}, {(r1*Sin[θ1[tr]] + r2*Sin[θ2[tr]]), (-r1*Cos[θ1[tr]] - r2*Cos[θ2[tr]])}} /. ans]}, PlotRange -> {{-1.6, 1.6}, {-1.6, 1.6}}]
     )
   ];
------------------------------------------------------------------------------------------------------------------------------------
12.5 二重振子のカオス発展を観察:10個の二重振子シュミレータの実行
------------------------------------------------------------------------------------------------------------------------------------
(*Mathematica*)
(* execution for 10-double pendulum simulator *)
(* double pendulum initial condition *)
{pendulums = 10, angle1 = 4 Pi/3, angle2 = 4 Pi/3, butterfly = 10^-12, time = 50};

(* double pendulum construction and initialization *)
objectList = Table[Unique[], {pendulums}];
Map[PendulumClass[#] &, objectList];
Map[initialize[#[angle1, angle2 + butterfly*RandomReal[{-1, 1}]]] &, objectList];

(* time integration and display  *)
Animate[Show[
  Map[pendulum[#[tr]] &, objectList]
  ], {tr, 0, time}, AnimationRepetitions -> 1, AnimationRate -> 1]

------------------------------------------------------------------------------------------------------------------------------------