2017년 7월 21일 금요일

Arduino 101 Demo: Using a Grove Kit for Plant Monitoring


DRAFT: June 5, 2016


Background


This tutorial demonstrates how Bluetooth LE can be used for measurement applications. More specifically, using an Arduino 101 and a Grove Kit, we will create a device for monitoring moisture and temperature in plants and crops.


Getting Started


You will need an Arduino 101 with a Grove shield and the following Grove sensors compatible with the Grove shield:
⦁ Temperature sensor, connected to analog port 3 (A3)
⦁ Moisture sensor, connected to analog port 2 (A2)
⦁ The Grove LED component, connected to digital port 4 (D4). This LED will be used to show when the Arduino has established a Bluetooth LE connection.

Figure 1: Arduino 101 with a Grove shield and all components connected in appropriate ports


Connect to App Inventor and start a new project.


Introduction


Many users of App Inventor create applications for helping their communities by addressing a significant problem. With the Internet of Things movement, we wish to make sure that young developers can continue to have this kind of impact in their communities, with the App Inventor Bluetooth LE component. This tutorial demonstrates how Arduino devices can be enable realistic applications. The target user for this demonstration application is anyone who normally grows plants or crops, such as a florist or a farmer, who wishes to monitor plants easily. With the Arduino Grove Kit, they can keep track of soil moisture, temperature and light exposure. For this tutorial, we will focus on moisture and temperature.


The first components


You will need several App Inventor components for your app:
⦁ A Button component named “ScanButton” that will be pressed to scan for Bluetooth LE devices.
⦁ A Label named “DeviceLabel” that will show a list of BLE devices found during scanning.
⦁ A BluetoothLE component available under Connectivity in the Palette.


Drag these components into the Viewer and assign their names. Set the text of “ScanButton” to “Scan for Devices”, and set the text “DeviceLabel” to “Devices: ”. Your screen should look as follows:

Figure 2: Design screen after adding initial components


We will now add behavior to the components. Switch to the Blocks editor and create a global variable named “address” and initialize it to an empty string. Drag the event handler called “when ScanButton.Click” to the blocks screen. In the palette, select the “BluetoothLE1” component and drag the block labeled “StartScanning”. This will initiate a scan for Bluetooth Low-Energy devices. In the same event handler, drag “DeviceLabel.Text” and set it to an empty text string.


From the “BluetoothLE1” palette, also drag out event handler “BluetoothLE1.DeviceFound”. This handler will fire every time a device is found during the scan. Drag out the “BluetoothLE1.DeviceList” block and assign it to the text of “DeviceLabel” inside of the DeviceFound event handler.


You should now have the following blocks:

Figure 3: Blocks that scan for Bluetooth LE devices


You can now run your app and find Bluetooth LE devices nearby. For this tutorial, we use an Arduino 101 device. You will need to download and install the Arduino IDE for your machine available at https://www.arduino.cc/en/Main/Software. You also need to change a few settings for the IDE to work with the 101. Follow the guidelines at https://www.arduino.cc/en/Guide/Arduino101.


You can then upload the Arduino code provided at the bottom of this tutorial under Arduino Code. After the Arduino code is successfully uploaded, you should be able to press “Scan for devices” and slowly devices will begin to show up in string format. For example, “98:4F:EE:0D:12:04 Garden -58, …”.

Figure 4: Screen after finding a multiple BLE devices, including the Arduino 101

Connecting to Arduino


Now that you can successfully scan for BLE devices, you can also connect to one of the found devices. For this part, you will need the following components:
⦁ A HorizontalArrangement component
⦁ A Button component named “ConnectButton” that will be used to connect to a BLE device. Set the text to “Connect”.
⦁ A Label component named “IndexLabel”. Set the text to “Connect at index: “.
⦁ A TextBox component named “IndexTextBox”. Select the property checkbox “NumbersOnly”. It may also be helpful to change the Hint property to “1, 2, etc.”
⦁ A Button component named “DisconnectButton” used to disconnect from a BLE device. Set the text to “Disconnect”.


You need to place the component “ConnectButton”, “IndexLabel”, and “IndexTextBox” within the first HorizontalArrangement. Place the “DisconnectButton” below that. Your app design should look as follows:

Figure 5: Screen layout for connecting and disconnecting from a BLE device


Now we add the functionality. In the Blocks editor, drag out the “.click” event for the “ConnectButton” component. Inside, set the value of the “global address” variable to “BluetoothLE1.FoundDeviceAddress”, connecting “IndexBox.Text” to the index parameter. After saving the device address, call “BluetoothLE1.ConnectWithAddress” with “global address” as the parameter. This allows your app to connect to one of the BLE devices listed in “BluetoothLE1.DeviceList”. The device list is 1-based.


From the palette, drag the event handler “BluetoothLE1.Connected”. This event is triggered when a connection to a BLE device is successful. Inside, call “BluetoothLE1.StopScanning” so that the phone stops scanning for new devices, and set “DisconnectButton.Enabled” to true, indicating that the a connection has been established.


Finally, you need to add the ability to disconnect from a Bluetooth LE device. To do this, drag the event handler “DisconnectButton.Click” and inside, call “BluetoothLE1.DisconnectWithAddress”, passing in the global variable “address” as the parameter for the block. This will disconnect the BLE Device. Within the same event handler, update “DisconnectButton.Enabled” to false, indicating that the BLE device has been disconnected.

Figure 6: Blocks that implement connecting and disconnecting functionality

You should now be able to connect to any BLE device nearby. With the Arduino 101 code provided, you can scan as before by pressing “Scan for devices”. When the device you wish to connect to shows up, put its index value in the text box and press “Connect”. An LED light on the Arduino should light up, indicating that it is connected. When you press “Disconnect”, you should see the LED turn off.


Communicating with Arduino


With a BLE connection established, you will now add the ability to communicate with the Arduino. For this part, you will need the following:
⦁ Two VerticalArrangement components.
⦁ Two HorizontalArrangement components.
⦁ A Label component named “MoistureLabel” with text set to “Current Moisture: “.
⦁ A Label named “MoistureDataLabel” with text set to “0”.
⦁ A Label named “TemperatureLabel” with text set to “Current Temperature: “.
⦁ A Label named “TemperatureDataLable” with text set to “0”.
⦁ A Button named “RefreshButton” with text set to “Refresh”.
⦁ A Label named “DataUpdateLable” with text set to “Data Update Inverval (in ms): “.
⦁ A TextBox named “DataUpdateTextBox” with the property “NumbersOnly” selected.
⦁ A Button named “ArduinoUpdateButton” with text set to “Update Arduino”.


Within the first VerticalArrangement, place the two HorizontalArrangements and the “RefreshButton”. Within the first HorizontalArrangement, place “MoistureLabel” and “MoistureDataLabel”. In the second HorizontalArrangement, place “TemperatureLabel” and “TemperatureDataLabel”. Finally, below that, place the “RefreshButton”. In the second VerticalArrangement, place “DataUpdateLabel”, “DataUpdateTextBox”, and “AdruinoUpdateButton”. Your designer screen should look similar to that shown in Figure 7.


Now you must implement the functionality. To do this, open the Blocks editor and drag out the “RefreshButton.Click” event handler. WIthin it, place the procedure “BluetoothLE1.ReadIntValue”. For the uuid parameters, put in Text components with the values “19B10000-E8F2-537E-4F6C-D104768A1214” and “19B10003-E8F2-537E-4F6C-D104768A1214” that correspond to the service and characteristic UUID used by the Arduino device for moisture. To retrieve the value, drag out a “BluetoothLE1.IntValueRead” EventHandler block and within it set the “MoistureDataLabel” texts to the “intValue” parameter provided by the event handler. Your blocks should look similar to those in Figure 8.

Figure 7: Design screen after adding component for reading sensor data
Figure 8: Blocks for reading the sensor data


At this point, when you press the “Refresh” button, you should see the moisture values updating. It is important to note that at the time of writing, the IntValueRead block does not distinguish between which integer value has been updated. For this reason we cannot use the “Refresh” button to update both the moisture and temperature values.


For automatic updates,  drag a “BluetoothLE1.IntValueChanged” EventHandler and update the text of “TemperatureDataLabel”. This allows us to update the temperature and moisture values separately.


Figure 9:  Event handler called when BLE device pushes updates to Android


One important factor when it comes to IoT applications is power consumption. Bluetooth Low Energy is used for devices that have limited power resources, such as an Arduino running on battery power. However, power consumption is also affected by how often the BLE device does work. In this case, the Arduino 101 will read sensor values every second. Of course this granularity in sensor data may not be necessary when monitoring crops so it would be useful to be able to make the time delay between measurements customizable. The Arduino code included for this demo is designed to allow for this delay time to be changed via bluetooth.


In the Blocks screen, drag the “ArduinoUpdateButton.Click” event handler to the screen. Also drag out a Procedure block. Inside of the procedure block place an “if then” control block and modify it to include an “else” field. Within the conditional, test if the value within “DataUpdateTextBox.Text” is a number. Within the “then” field set the value of global “delayTime” to the value of “DataUpdateTextBox.Text”, and within the “else” field set the value of “delayTime” to numerical value 1000. Within “ArduinoUpdateButton.Click”, make a call to the procedure you just defined and then call “BluetoothLE1.WriteIntValue.” The required uuid fields will be “19B10000-E8F2-537E-4F6C-D104768A1214”, and “19B10001-E8F2-537E-4F6C-D104768A1214” respectively. For the “uuid” field, connect the global “delayTime”, and for the “offset” use a value of 0. Your blocks should look as follows:


Figure 10: Blocks that update the Arduino’s refresh interval





Snap-to-Grid BUT no cannibalism problem


I am attempting to have my flagsprite(s) and my starsprite(s) on a grid together at the same time as the player drags each item from the bottom onto the checkerboard grid. I am looking to have the sprites "Snap-To-Grid" but NOT join together and as Scott put it in his tutorial cannibalize each other. I need to somehow combine these two versions to meet my goals of No Cannibalism but still Snap-To-Grid.

Any suggestions? I value your input as I have taken the time to recreate each scenario.

--
so if there are 2 images sprites in the same position, which one do you like to move then?

--
I move both of them ... one at a time but i can move both sprites in both versions. One snaps to grid as programmed but when it comes in contact with another sprite it links together and won't separate, The other doesn't join together when they cross each other's path but now it doesn't snap to grid. 

I need snap to grid but no joining together when they cross paths on the canvas.

--
This is a modification of my checkers example with two checker pieces instead of one.
It does both snapping and avoids cannibalism.
SnapToGridTwo.aia

--
SUCCESS: I have attached a pic of the version in which I was able to get a good Snap-to-Grid without the other sprite eating the other one. I found that I had a better "Snap" with the original version from you tube where we used the quotient instead of the remainder version. The remainder version left the sprite snapped to the middle of the box grid for some reason. Probably something I did but when I switched back I was able to get the sprites to snap to the proper corners.

As I continue to work on the other components I will update and humbly bow before your wizardry on app inventor 2 before I complete the rest of the app and show you when it is done.

--
Great!

--