Raspberry Pi (11) LAMP setup

Raspberry PiにLAMP環境を作る

install

念のため、updateしておく。

pi@raspberrypi:~ $ sudo apt-get update

AMPを一気にinstallする

pi@raspberrypi:~ $ sudo apt-get install -y apache2 php5 mysql-server

Apache2 Debian Default Page をみる

http://192.168.11.139/

PHP動作確認

Document Rootsは、/var/www/html の下。そこにinfo.php ファイルを作って、PHP動作確認する。

pi@raspberrypi:~ $ cd /var/www/html

管理者権限で、ファイルを新規作成。

root@raspberrypi:/var/www/html$ sudo nano info.php

またはrootユーザーになって

root@raspberrypi:/var/www/html#  nano info.php

ファイルの中身を確認

root@raspberrypi:/var/www/html# cat info.php
<?php
phpinfo();
?>

ブラウザーから、PHPの設定情報が見れる。

http://192.168.11.139/info.php

 

WeMos (14) WiFiManager

WeMos のWiFiが、前回のようにSSIDとPASSWORDをコードに書き込む方法の他に、オンライン変更できるような方法もある。

WiFiManager というライブラリを使うと簡単にできる

https://github.com/tzapu/WiFiManager

このソースを参考に試してみる。

まず、ライブラリマネージャーから、WiFiManagerを検索して、インストールする。

ライブラリを使える状態にすると

#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>

void setup() {
  WiFiManager wifiManager;
  wifiManager.autoConnect();
}

void loop() {
}

だけで上のユースケースが満たされて大変便利だ…。標準でWebUIもついてる。

 

WeMos (13) Web on WiFi

いよいよ内蔵WiFiを活用する時期が来た!

前回のセンサー情報をWebからでも見れるようにする。

処理の流れ

setup() {
    WiFi初期化
    Web初期化
    センサー初期化
}
loop() {
    If (Webからリクエスト) 
      .1 パラメタよりLED点/滅
      .2 センサー情報取得
      .3 クライアントに返信
    Else
      .1 センサー情報取得
      .2 LCDに情報表示
}

setup()

  • WiFi 初期化:内蔵WiFiをアクセスポイントに接続
  • Web初期化:内蔵Webサーバを立ち上げる
  • センサー初期化:BMP280を初期化

loop()

  • Webからのリクエストをチェックする

システム構成

完成したプログラム

/*
 * 
 */
#include <Wire.h> 
#include <Adafruit_BMP280.h>
#include <LiquidCrystal_I2C.h>
 
//For SPI connection!
#define BMP_SCK D5
#define BMP_MISO D6
#define BMP_MOSI D7 
#define BMP_CS D3

Adafruit_BMP280 bmp; // I2C
// Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
// Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO,  BMP_SCK);

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

#include <ESP8266WiFi.h>
 
const char* ssid = "SSID";
const char* password = "WIFI PASS";
 
int ledPin = BUILTIN_LED;
WiFiServer server(80);

void setup()
{
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);

  lcd.begin(0,2);  // sda=GPIO_0, scl=GPIO_2

  lcd.init();

  // Turn on the backlight.
  lcd.backlight();
    
  // Connect to WiFi network
  lcd.print("Connect to ");
  lcd.println(ssid);
 
  WiFi.begin(ssid, password);
  lcd.setCursor(0, 1);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    lcd.print(".");
  }
  lcd.println("");
  lcd.println("WiFi connected");
 
  // Start the server
  server.begin();
  lcd.println("Server started");
  
  // Print the IP address
  lcd.setCursor(0, 0);
  lcd.print(WiFi.localIP());
  lcd.println("/");

  if (!bmp.begin(0x76)) 
  {
    lcd.println("Could not find BMP180 or BMP085 sensor at 0x77");
    while (1) {}
  }
}

void lcd_show()
{
  lcd.setCursor(0, 1);
  lcd.print(bmp.readTemperature());
  lcd.print("C, ");
  lcd.print(bmp.readPressure() / 100 );
  lcd.print("P ");
  // print the number of seconds since reset:
  lcd.print(millis() / 1000);
  delay(2000);

}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    lcd_show();
    delay(1);
    return;
  }
 
  // Wait until the client sends some data
  lcd.println("new client");
  // while(!client.available()){
  //   delay(1);
  // }
 
  // Read the first line of the request
  String request = client.readStringUntil('\r');
  lcd.println(request);
  client.flush();
 
  // Match the request
 
  int value = LOW;
  if (request.indexOf("/LED=ON") != -1) {
    digitalWrite(ledPin, LOW);
    value = HIGH;
  } 
  if (request.indexOf("/LED=OFF") != -1){
    digitalWrite(ledPin, HIGH);
    value = LOW;
  }
 
 
 
  // Return the response
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
 
  client.print("Temp = ");
  client.print(bmp.readTemperature());
  client.println(" Celsius <br>");
  client.print("Pres = ");
  client.print(bmp.readPressure());
  client.println(" Pascal <br>");

  client.print("Led pin is now: ");
 
  if(value == HIGH) {
    client.print("On");  
  } else {
    client.print("Off");
  }
  client.println("<br><br>");
  client.println("Click <a href=\"/LED=ON\">here</a> turn the LED ON<br>");
  client.println("Click <a href=\"/LED=OFF\">here</a> turn the LED OFF<br>");
  client.println("</html>");
 
  delay(1);
  lcd.println("Client disconnected");
 
}


 

WeMos (9) I2C OLED表示

[0.96 インチ 4Pin IIC I2C ブルー OLED ディスプレイ モジュール Arduino対応]を使ってみる。

主な仕様は次のようになっています。

  • I2C通信
  • ディスプレイコントローラ: SSD1306
  • 解像度: 128×64
  • 電圧: 3.3V-5V

 

こちらを参考にして、すんなりできた。

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
#define OLED_RESET 0  // GPIO0
Adafruit_SSD1306 OLED(OLED_RESET);
 
void setup()   {
  OLED.begin();
  OLED.clearDisplay();
 
  //Add stuff into the 'display buffer'
  OLED.setTextWrap(false);
  OLED.setTextSize(1);
  OLED.setTextColor(WHITE);
  OLED.setCursor(0,0);
  OLED.println("automatedhome.party");
 
  OLED.display(); //output 'display buffer' to screen  
  OLED.startscrollleft(0x00, 0x0F); //make display scroll 
} 
 
void loop() {
}

これて、i2c 複数繋いて、いい感じ。

 
参考

WeMos (8) BMP280 SPI気圧温度表示

気圧センサーとNikia 5110と同時に使いたい。

まず前回BMP180センサーの利用を考える。こちらはI2Cで通信する。WemosのPinoutを見ると、SPIとI2Cは共有するなく、同時に使えそうだが、しかしいくら試してもうまくいかない。

そこでBMP280センサーの利用を考える。こちらは、SPIとI2C両方利用可能。

The chip select (CSB) and serial data output (SDO) pins of the BMP 280 are necessary only when SPI-based (four-wire) communication is applied. For SPI, keep an eye on the pin assignments: VCC-VCC/GND-GND/SCL-SCK/SDA-MOSI/CSB-SS/SDO-MISO. Now to the official schematic of the GY-BM E/P 280 module:

まずSPIで気圧を測って見る。

/***************************************************************************
  This is a library for the BMP280 humidity, temperature & pressure sensor
  Designed specifically to work with the Adafruit BMEP280 Breakout 
  ----> http://www.adafruit.com/products/2651
  These sensors use I2C or SPI to communicate, 2 or 4 pins are required 
  to interface.
  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!
  Written by Limor Fried & Kevin Townsend for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ***************************************************************************/

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

#define BMP_SCK D5
#define BMP_MISO D6
#define BMP_MOSI D7 
#define BMP_CS D0

// Adafruit_BMP280 bmp; // I2C
Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
// Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO,  BMP_SCK);

void setup() {
  Serial.begin(9600);
  Serial.println(F("BMP280 test"));
  
  if (!bmp.begin()) {  
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
    while (1);
  }
}

void loop() {
    Serial.print(F("Temperature = "));
    Serial.print(bmp.readTemperature());
    Serial.println(" *C");
    
    Serial.print(F("Pressure = "));
    Serial.print(bmp.readPressure());
    Serial.println(" Pa");

    Serial.print(F("Approx altitude = "));
    Serial.print(bmp.readAltitude(1013.25)); // this should be adjusted to your local forcase
    Serial.println(" m");
    
    Serial.println();
    delay(2000);
}

シリアルから、ちゃんと表示できた。次はNikia 5110とSPIを仲良くできるか。

Temperature = 26.45 *C
Pressure = 100922.89 Pa
Approx altitude = 33.53 m

次は、気圧センサーとNikia 5110同時に使うため、SPIで通信する環境を作る。

 

Arduino UNO (7) L298N

Arduino UNO でCarのモーターを動かす。

接続方法

Library追加

L298N Dual H-Bridge library for controlling via PWN 2 motors

https://github.com/yohendry/arduino_L298N

テストプログラム

#include <L298N.h>
const int ENA = 6;
const int IN1 = 9;
const int IN2 = 7;
const int IN3 = 2;
const int IN4 = 4;
const int ENB = 3;
L298N driver(ENA,IN1,IN2,IN3,IN4,ENB); 
int time_delay = 500;
int speed = 150;
void setup()
{
}

void loop()
{
  driver.forward(speed,time_delay);
  driver.full_stop(time_delay);
  driver.turn_right(speed,time_delay);
  driver.full_stop(time_delay);
  driver.turn_left(speed,time_delay);
  driver.full_stop(time_delay);
  driver.backward(speed,time_delay);
}

動く様子

 

 

Arduino UNO (6) i2c scanner

i2c のアドレスを確かめるため、下記のプログラムを動かせばいい。

// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, November 27, 2015.
//    Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//
 
#include <Wire.h>
 
 
void setup()
{
  Wire.begin();
 
  Serial.begin(9600);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);           // wait 5 seconds for next scan
}

結果は、シリアルモニターで繰り返し表示する。

Scanning...
I2C device found at address 0x27  !
done

Scanning...
I2C device found at address 0x27  !
done

Scanning...
I2C device found at address 0x27  !
done

 

WeMos (5) TM1637 7段4桁LED表示

7段4桁LED を表示してみる

参考のURLの通り、試しただけ。

TM1637 用ライブラリをインストール

  1. ライブラリをダウンロード
    https://github.com/avishorp/TM1637
  2. ライブラリを Arduino IDE にインストール
  3. Arduino IDE の [スケッチ] → [ライブラリを使用] → [ライブラリをインストール…] からダウンロードしたライブラリ ZIP を選択しインストールする。

繋がる

const int CLK = D6; //Set the CLK pin connection to the display
const int DIO = D5; //Set the DIO pin connection to the display

スケッチを作成する

#include <TM1637Display.h>
 
const int CLK = D6; //Set the CLK pin connection to the display
const int DIO = D5; //Set the DIO pin connection to the display
 
int numCounter = 0;
 
TM1637Display display(CLK, DIO); //set up the 4-Digit Display.
 
void setup()
{
 display.setBrightness(0x0a); //set the diplay to maximum brightness
}
 
 
void loop()
{
 for(numCounter = 0; numCounter < 1000; numCounter++) //Iterate numCounter
 {
 display.showNumberDec(numCounter); //Display the numCounter value;
 delay(1000);
 }
}

動作を確認する

  1. Arduino IDE にてコンパイル&書き込み
  2. 時間をカウントすることが確認できる

参考

  • http://www.esp8266learning.com/tm1637-7-segment-display-example.php#codesyntax_3

WeMos (4) 1602 LCD i2c 表示

1602 LCD直接繋ぐと、6つのデジタルポートを占有(4つデータワイヤ+2の制御ワイヤが必要)し、GPIOはたくさん消耗するので、i2cを利用すると2つのアナログポートが足りる。

下記のURLから、ライブラリを利用

https://github.com/agnunez/ESP8266-I2C-LCD1602

しかし、表示がない!

持っている他のUno, Nanaに試したら、ちゃんと表示した。

LCD address to 0x27も間違いない。

どうして?

/*
 * 1602 LCD Sample with LiquidCrystal_I2
 * https://github.com/agnunez/ESP8266-I2C-LCD1602
 * 
 * PCF8574-----1602LCD-----WeMos
 * A0                 -----GND
 * A1                 -----GND
 * A2                 -----GND
 * VSS                -----GND
 * P0     ----- RS
 * P1     ----- RW
 * P2     ----- EN
 * P3     ----- B/L
 * P4     ----- D4
 * P5     ----- D5
 * P6     ----- D6
 * P7     ----- D7
 * VDD                -----5V
 * 
 * SDA                -----D3(GPIO_0)
 * SCL                -----D4(GPIO_2)
 * 
 */
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
  lcd.begin(0,2);  // sda=GPIO_0, scl=GPIO_2
  // Print a message to the LCD.
  lcd.print("hello, world!");
}

void loop()
{
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis() / 1000);
}

「未完成!!!」したまま、やはりきになる。

// * SDA —–D3(GPIO_0)
// * SCL —–D4(GPIO_2)

接続方法が間違った感じ!

いろいろなサイト参考して、とりあえず、下記の接続方法でうまくいけそう。

* SDA —–D1
* SCL —–D2

Pin out を調べたら、I2Cその一通りのみの感じでした。

i2c scannerのプログラムで、ちゃんと検出できた

Scanning...
I2C device found at address 0x27 !
I2C device found at address 0x77 !
done

接続を見直して、今度うまくいく!

/*
 * 1602 LCD Sample with LiquidCrystal_I2
 * https://github.com/agnunez/ESP8266-I2C-LCD1602
 * 
 * PCF8574-----1602LCD-----WeMos
 * A0                 -----GND
 * A1                 -----GND
 * A2                 -----GND
 * VSS                -----GND
 * P0     ----- RS
 * P1     ----- RW
 * P2     ----- EN
 * P3     ----- B/L
 * P4     ----- D4
 * P5     ----- D5
 * P6     ----- D6
 * P7     ----- D7
 * VDD                -----5V
 * 
 * SDA                -----D3(GPIO_0)
 * SCL                -----D4(GPIO_2)
 * 
 */
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
  lcd.begin(0,2);  // sda=GPIO_0, scl=GPIO_2

  lcd.init();

  // Turn on the backlight.
  lcd.backlight();
    
  // Print a message to the LCD.
  lcd.print("hello, world!");
}

void loop()
{
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis() / 1000);
}

 

おまけに、接続した気圧センサーのアドレスは0x77もわかった。

 

参考:

  • https://www.losant.com/blog/how-to-connect-lcd-esp8266-nodemcu
  • http://nopnop2002.webcrow.jp/WeMos/WeMos-24.html

Arduino UNO (4) BLE

いよいよBLEの実験を開始。Bluetooth 4.0 モジュールを使って、Android AppとArduinoを通信する。

まず持っているBluetooth 4.0 モジュールは、HM10 互換というから、参考になるものを探す。

なぜか、接続表のように、RX0/TX0からBluetoothモジュールとUNOボードを接続すると、プログラムを書き込みできない。

一旦切り離して、プログラムを書き込みおわったら、また接続すればうまくいく。

#もしかしてこれは常識???

Bluetooth 4.0 Arduino UNO R3ボード
VCC 5V
GND GND
TXD RX0(pin0)
RXD TX0(pin1)

そのため接続表のように、D7/D8からBluetoothモジュールとUNOボードを接続する。

Bluetooth 4.0 Arduino UNOボード
VCC 5V
GND GND
TXD pin 7
RXD pin 8

プログラム:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(7, 8); // RX, TX  
// Connect HM10      Arduino Uno
//     Pin 1/TXD          Pin 7
//     Pin 2/RXD          Pin 8

void setup() {  
  Serial.begin(9600);
  // If the baudrate of the HM-10 module has been updated,
  // you may need to change 9600 by another value
  // Once you have found the correct baudrate,
  // you can update it using AT+BAUDx command 
  // e.g. AT+BAUD0 for 9600 bauds
  mySerial.begin(9600);
}

void loop() {  
  char c;
  if (Serial.available()) {
    c = Serial.read();
    mySerial.print(c);
  }
  if (mySerial.available()) {
    c = mySerial.read();
    Serial.println(c);    
  }
}

Android Appは、BleSerialPortというソフトウエアをインストールして試す。

Android Appから送信したデータは、シリアルモニタで表示される。

スクリーンショット 2017-09-07 15.38.35

次の実験は、受信データを1602LCDで表示する。

参考:

  • http://osoyoo.com/ja/2016/10/27/bluetooth-4-0-hm-10-android-arduino/