Last active
April 3, 2018 16:38
-
-
Save badarshahzad/de809ff034ca26b194b0573f6052e760 to your computer and use it in GitHub Desktop.
Android Things MCP3008 example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.badarshahzad54.pcbs; | |
import android.app.Activity; | |
import android.app.FragmentTransaction; | |
import android.graphics.Rect; | |
import android.os.Bundle; | |
import android.os.Handler; | |
import android.os.PersistableBundle; | |
import android.util.Log; | |
import android.widget.Switch; | |
import android.widget.TextView; | |
import android.widget.Toolbar; | |
import com.badarshahzad54.pcbs.mcp3008.MCP3008; | |
import com.badarshahzad54.pcbs.modelThings.AppliancesLog; | |
import com.badarshahzad54.pcbs.presentation.fragments.BillFragment; | |
import com.badarshahzad54.pcbs.presentation.fragments.HomeFragment; | |
import com.badarshahzad54.pcbs.presentation.utils.BoomMenuesUtils; | |
import com.google.android.things.pio.Gpio; | |
import com.google.firebase.database.DataSnapshot; | |
import com.google.firebase.database.DatabaseError; | |
import com.google.firebase.database.DatabaseReference; | |
import com.google.firebase.database.FirebaseDatabase; | |
import com.google.firebase.database.ServerValue; | |
import com.google.firebase.database.ValueEventListener; | |
import com.nightonke.boommenu.Animation.BoomEnum; | |
import com.nightonke.boommenu.BoomButtons.BoomButton; | |
import com.nightonke.boommenu.BoomButtons.ButtonPlaceEnum; | |
import com.nightonke.boommenu.BoomButtons.TextInsideCircleButton; | |
import com.nightonke.boommenu.BoomMenuButton; | |
import com.nightonke.boommenu.ButtonEnum; | |
import com.nightonke.boommenu.OnBoomListener; | |
import com.nightonke.boommenu.Piece.PiecePlaceEnum; | |
import java.io.IOException; | |
/** | |
* Skeleton of an Android Things activity. | |
* <p> | |
* Android Things peripheral APIs are accessible through the class | |
* PeripheralManagerService. For example, the snippet below will open a GPIO pin and | |
* set it to HIGH: | |
* <p> | |
* <pre>{@code | |
* PeripheralManagerService service = new PeripheralManagerService(); | |
* mLedGpio = service.openGpio("BCM6"); | |
* mLedGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); | |
* mLedGpio.setValue(true); | |
* }</pre> | |
* <p> | |
* For more complex peripherals, look for an existing user-space driver, or implement one if none | |
* is available. | |
* | |
* @see <a href="https://github.com/androidthings/contrib-drivers#readme">https://github.com/androidthings/contrib-drivers#readme</a> | |
*/ | |
/* | |
Initializing with a Raspberry Pi 3B and a TMP36 connected to ADC CH 0. | |
Can change these pin numbers in your own projects to be the proper board pins. | |
Pinout for sample like so: | |
ADC channel 0 -|* |- 5v in | |
ADC channel 1 -| |- 5v in | |
ADC channel 2 -| |- Analog GND (For this sample app, I used this ground) | |
ADC channel 3 -| |- Clock | |
ADC channel 4 -| |- MISO pin on board (sometimes listed as D-OUT on chip diagram) | |
ADC channel 5 -| |- MOSI pin on board (sometimes listed as DIN on chip diagram) | |
ADC channel 6 -| |- Chip select (CS) | |
ADC channel 7 -| |- Digital GND (For this sample app, I left this GND disconnected) | |
I wired BCM12 to CS, BCM21 to Clock, BCM16 to MOSI (D-OUT) and BCM20 to MISO (D-IN) | |
*/ | |
//TODO: Give proper referance https://github.com/PaulTR/AndroidThingsMCP3008ADC/blob/master/MCP3008/app/src/main/java/com/paultrebilcoxruiz/mcp3008/MainActivity.java | |
public class MainActivity extends Activity { | |
private static final String TAG = MainActivity.class.getSimpleName(); | |
private static final int INTERVAL_BETWEEN_BLINKS_MS = 500; | |
//pin number 33 | |
private static final String GPIO_PIN_NAME = "BCM13"; | |
int highLow = 0; | |
int hightScore = 0; | |
private Handler handler = new Handler(); | |
private Gpio ledGpio; | |
private Switch switch1; | |
private TextView count; | |
private TextView device1; | |
private Toolbar toolbar; | |
private BoomMenuButton boomMenuButton; | |
//firebase | |
private DatabaseReference firebaseDatabase; | |
private AppliancesLog appliancesLog; | |
private FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); | |
private HomeFragment homeFragment; | |
//Here is the MCP3008 communication class | |
private MCP3008 mMCP3008; | |
private Handler handlerForMCP3008; | |
/** | |
* ADC read runnble | |
*/ | |
private Runnable mReadAdcRunnable = new Runnable() { | |
private static final long DELAY_MS = 3000L; // 3 seconds | |
@Override | |
public void run() { | |
if (mMCP3008 == null) { | |
return; | |
} | |
try { | |
Log.i("MCP3008", "ADC 0: " + mMCP3008.readAdc(0x0)); | |
Log.i("MCP3008", "ADC 1: " + mMCP3008.readAdc(0x1)); | |
Log.i("MCP3008", "ADC 2: " + mMCP3008.readAdc(0x2)); | |
Log.i("MCP3008", "ADC 3: " + mMCP3008.readAdc(0x3)); | |
Log.i("MCP3008", "ADC 4: " + mMCP3008.readAdc(0x4)); | |
Log.i("MCP3008", "ADC 5: " + mMCP3008.readAdc(0x5)); | |
Log.i("MCP3008", "ADC 6: " + mMCP3008.readAdc(0x6)); | |
Log.i("MCP3008", "ADC 7: " + mMCP3008.readAdc(0x7)); | |
} catch (IOException e) { | |
Log.i("MCP3008", "Something went wrong while reading from the ADC: " + e.getMessage()); | |
} | |
handlerForMCP3008.postDelayed(this, DELAY_MS); | |
} | |
}; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
/** | |
* MCP3008 initialize | |
*/ | |
try { | |
mMCP3008 = new MCP3008("BCM12", "BCM21", "BCM16", "BCM20"); | |
mMCP3008.register(); | |
} catch (IOException e) { | |
Log.e("MCP3008", "MCP initialization exception occurred: " + e.getMessage()); | |
} | |
handlerForMCP3008 = new Handler(); | |
handlerForMCP3008.post(mReadAdcRunnable); | |
//good place to create the Realm instance | |
/* Realm.init(this); | |
RealmConfiguration configuration = new RealmConfiguration | |
.Builder() | |
.name("pcbs_things.realm") | |
.deleteRealmIfMigrationNeeded() | |
.build(); | |
//development phase & as I need clean database each time | |
Realm.deleteRealm(configuration); | |
//helo to work with realm and realm objects | |
Realm.setDefaultConfiguration(configuration); | |
*/ | |
HomeFragment homeFragment = new HomeFragment(); | |
getFragmentManager().beginTransaction() | |
.add(R.id.fragment_container,homeFragment,"homefragment") | |
.commit(); | |
// setTitle("Bachat Smart Board"); | |
initViews(); | |
initBoomMenu(); | |
initFirebase(); | |
} | |
@Override | |
protected void onDestroy() { | |
super.onDestroy(); | |
if (mMCP3008 != null) { | |
mMCP3008.unregister(); | |
} | |
if (handlerForMCP3008 != null) { | |
handlerForMCP3008.removeCallbacks(mReadAdcRunnable); | |
} | |
} | |
private void initViews() { | |
boomMenuButton = findViewById(R.id.bmb); | |
toolbar = findViewById(R.id.toolbar); | |
setActionBar(toolbar); | |
} | |
private void initBoomMenu() { | |
//boommenu | |
boomMenuButton.setButtonEnum(ButtonEnum.TextInsideCircle); | |
boomMenuButton.setPiecePlaceEnum(PiecePlaceEnum.DOT_8_3); | |
boomMenuButton.setButtonPlaceEnum(ButtonPlaceEnum.SC_8_3); | |
boomMenuButton.setBoomEnum(BoomEnum.HORIZONTAL_THROW_2); | |
boomMenuButton.setDraggable(true); | |
homeFragment = new HomeFragment(); | |
fragmentTransaction.add(R.id.fragment_container, homeFragment); | |
fragmentTransaction.commit(); | |
boomMenuButton.setOnBoomListener(new OnBoomListener() { | |
@Override | |
public void onClicked(int index, BoomButton boomButton) { | |
switch(index){ | |
case 0: | |
homeFragment = new HomeFragment(); | |
fragmentTransaction = getFragmentManager().beginTransaction(); | |
fragmentTransaction.replace(R.id.fragment_container, homeFragment); | |
fragmentTransaction.commit(); | |
break; | |
case 1: | |
BillFragment billFragment = new BillFragment(); | |
fragmentTransaction = getFragmentManager().beginTransaction(); | |
fragmentTransaction.replace(R.id.fragment_container, billFragment); | |
fragmentTransaction.commit(); | |
break; | |
case 3: | |
//Intent intent_start_Wifi = new Intent(Settings.ACTION_WIFI_SETTINGS); | |
//startActivity(intent_start_Wifi); | |
break; | |
} | |
} | |
@Override | |
public void onBackgroundClick() { | |
} | |
@Override | |
public void onBoomWillHide() { | |
} | |
@Override | |
public void onBoomDidHide() { | |
} | |
@Override | |
public void onBoomWillShow() { | |
} | |
@Override | |
public void onBoomDidShow() { | |
} | |
}); | |
/***** | |
* TODO: the number of dots on floatbutton 9 but the menus is 8 so | |
* I will later add suitable menu | |
* TODO: remember I have add -1 in the getPiecePlaceEnum to make 8 menus | |
*/ | |
//bmb.addBuilder(); | |
for (int i = 0; i < boomMenuButton.getPiecePlaceEnum().pieceNumber(); i++) { | |
TextInsideCircleButton.Builder builder = new TextInsideCircleButton.Builder() | |
.normalImageRes(BoomMenuesUtils.navigationMenuImages[i]) | |
.normalText(BoomMenuesUtils.navigationMenuStrings[i]) | |
.imagePadding(new Rect(8, 8, 8, 16)); | |
boomMenuButton.addBuilder(builder); | |
// bmb.addBuilder(getSimpleCircleButtonBuilder()); | |
} | |
} | |
private void initFirebase() { | |
final String FIREBASE_LOGS = "logs"; | |
final String TAG = "ElectricityMonitor"; | |
final String FIREBASE_ONLINE_ENDPOINT = "/online"; | |
final String FIREBASE_INFO_CONNECTED = ".info/connected"; | |
/******************** | |
* Appliances Log Begin | |
*/ | |
firebaseDatabase = FirebaseDatabase.getInstance().getReference(); | |
final String key = firebaseDatabase.child(FIREBASE_LOGS).push().getKey(); | |
appliancesLog = new AppliancesLog(); | |
final DatabaseReference onlineRef = firebaseDatabase.child(FIREBASE_INFO_CONNECTED); | |
final DatabaseReference currentUserRef = firebaseDatabase.child(FIREBASE_ONLINE_ENDPOINT); | |
onlineRef.addValueEventListener(new ValueEventListener() { | |
@Override | |
public void onDataChange(DataSnapshot dataSnapshot) { | |
Log.d(TAG, "onDataChange: "+ dataSnapshot); | |
if(dataSnapshot.getValue(Boolean.class)){ | |
appliancesLog.setTimestampOn(ServerValue.TIMESTAMP); | |
final DatabaseReference currentLogDbRef = | |
firebaseDatabase.child(FIREBASE_LOGS).child(key); | |
currentUserRef.setValue(true); | |
currentUserRef.onDisconnect().setValue(false); | |
appliancesLog.setTimestampOff(ServerValue.TIMESTAMP); | |
currentLogDbRef.onDisconnect().setValue(appliancesLog); | |
} | |
} | |
@Override | |
public void onCancelled(DatabaseError databaseError) { | |
Log.d(TAG, "onCancelled: "+ databaseError); | |
} | |
}); | |
/******************** | |
* Appliances Log End | |
*/ | |
/* | |
firebaseDatabase = FirebaseDatabase.getInstance().getReference(); | |
//FirebaseDatabase.getInstance().setPersistenceEnabled(true); | |
firebaseDatabase.setValue(hightScore); | |
firebaseDatabase.addValueEventListener(new ValueEventListener() { | |
@Override | |
public void onDataChange(DataSnapshot dataSnapshot) { | |
hightScore = Integer.valueOf(dataSnapshot.getValue().toString()); | |
Log.i(TAG, "onDataChange: 1"+dataSnapshot.getValue()); | |
Log.i(TAG, "onDataChange: 2"+dataSnapshot.getKey()); | |
Log.i(TAG, "onDataChange: 3"+dataSnapshot.getRef()); | |
if(highLow==1){ | |
device1.setText("ON"); | |
turnDevice1(true); | |
count.setText("Count:" + hightScore); | |
Log.i(TAG, "onDataChange: ON"); | |
}else { | |
device1.setText("Off"); | |
count.setText("Count:" + hightScore); | |
turnDevice1(false); | |
Log.i(TAG, "onDataChange: OFF"); | |
} | |
Log.i(TAG, "onDataChange: "); | |
} | |
@Override | |
public void onCancelled(DatabaseError databaseError) { | |
Log.i(TAG, "onCancelled: Database exception"); | |
} | |
}); | |
count = findViewById(R.id.count); | |
device1 = findViewById(R.id.device1); | |
//count.setText(count.getText()+""+ip); | |
try { | |
// Step 1. Create GPIO connection. | |
ledGpio = service.openGpio(GPIO_PIN_NAME); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
switch1 = (Switch) findViewById(R.id.switch1); | |
switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |
@Override | |
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { | |
Log.i(TAG, "Value Switch 1: " + isChecked); | |
if (isChecked) { | |
device1.setText("On"); | |
turnDevice1(true); | |
hightScore++; | |
Log.i(TAG, "onCheckedChanged: " + hightScore); | |
count.setText("Count:" + hightScore); | |
//Device device = new Device(0,true); | |
firebaseDatabase.setValue(hightScore); | |
} else { | |
turnDevice1(false); | |
hightScore++; | |
count.setText("Count:" + hightScore); | |
device1.setText("Off"); | |
} | |
} | |
}); | |
*/ | |
} | |
/** | |
* Turn gpio pin on and off | |
* @param onOff | |
*/ | |
private void turnDevice1(boolean onOff) { | |
if (onOff) { | |
try { | |
ledGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_HIGH); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} else { | |
try { | |
ledGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
/** | |
* Testing Code: This snippet code take from the https://github.com/androidthings/sample-button | |
*/ | |
/* | |
protected void onDestroy() { | |
super.onDestroy(); | |
// Step 4. Remove handler events on close. | |
handler.removeCallbacks(mBlinkRunnable); | |
// Step 5. Close the resource. | |
if (ledGpio != null) { | |
try { | |
ledGpio.close(); | |
} catch (IOException e) { | |
Log.e(TAG, "Error on PeripheralIO API", e); | |
} | |
} | |
} | |
private Runnable mBlinkRunnable = new Runnable() { | |
@Override | |
public void run() { | |
// Exit if the GPIO is already closed | |
if (ledGpio == null) { | |
return; | |
} | |
try { | |
// Step 3. Toggle the LED state | |
ledGpio.setValue(!ledGpio.getValue()); | |
// Log.i(TAG, "thread is running****"); | |
// Step 4. Schedule another event after delay. | |
handler.postDelayed(mBlinkRunnable, INTERVAL_BETWEEN_BLINKS_MS); | |
} catch (IOException e) { | |
Log.e(TAG, "Error on PeripheralIO API", e); | |
} | |
} | |
}; | |
*/ | |
//Just to watch the Life Cycle | |
/** | |
* When I run the applicatino onStart and onResume called when I stop not method called | |
* When I again run the applicaiotn from studio then onPause then on stop but not onStart | |
* onCreate or onResume called intereseting | |
* When rerun the applciaiton again onStart and onResume | |
*/ | |
//Life Cycle | |
@Override | |
protected void onResume() { | |
super.onResume(); | |
//here we will get the list | |
Log.i(TAG, "onResume: "); | |
} | |
@Override | |
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) { | |
super.onSaveInstanceState(outState, outPersistentState); | |
Log.i(TAG, "onSaveInstanceState: "); | |
} | |
@Override | |
protected void onPause() { | |
super.onPause(); | |
Log.i(TAG, "onPause: "); | |
} | |
@Override | |
protected void onStart() { | |
super.onStart(); | |
Log.i(TAG, "onStart: "); | |
} | |
@Override | |
protected void onRestart() { | |
super.onRestart(); | |
Log.i(TAG, "onRestart: "); | |
} | |
@Override | |
protected void onStop() { | |
super.onStop(); | |
Log.i(TAG, "onStop: "); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.badarshahzad54.pcbs.mcp3008; | |
import com.google.android.things.pio.Gpio; | |
import com.google.android.things.pio.PeripheralManagerService; | |
import java.io.IOException; | |
/* | |
Paul Trebilcox-Ruiz | |
[email protected] | |
Library for communicating with the MCP3008 Analog to Digital Converter. | |
Based on an Arduino library by: Uros Petrevski (https://github.com/nodesign/MCP3008) | |
Ported from Python code originaly written by Adafruit learning system for rPI: | |
http://learn.adafruit.com/send-raspberry-pi-data-to-cosm/python-script | |
Initializing with a Raspberry Pi 3B and a TMP36 connected to ADC CH 0. | |
Can change these pin numbers in your own projects to be the proper board pins. | |
Pinout for sample like so: | |
ADC channel 0 -|* |- VIN | |
ADC channel 1 -| |- VIN | |
ADC channel 2 -| |- Analog GND (For this sample app, I used this ground) | |
ADC channel 3 -| |- Clock | |
ADC channel 4 -| |- MISO pin on board (sometimes listed as D-OUT on chip diagram) | |
ADC channel 5 -| |- MOSI pin on board (sometimes listed as DIN on chip diagram) | |
ADC channel 6 -| |- Chip select (CS) | |
ADC channel 7 -| |- Digital GND (For this sample app, I left this GND disconnected) | |
While testing I wired BCM12 to CS, BCM21 to Clock, BCM16 to MOSI (D-OUT) and | |
BCM20 to MISO (D-IN) | |
*/ | |
//TODO: give proper referance | |
//https://github.com/PaulTR/AndroidThingsMCP3008ADC/blob/master/MCP3008/app/src/main/java/com/paultrebilcoxruiz/mcp3008/MainActivity.java | |
public class MCP3008 { | |
private final String csPin; | |
private final String clockPin; | |
private final String mosiPin; | |
private final String misoPin; | |
private Gpio mCsPin; | |
private Gpio mClockPin; | |
private Gpio mMosiPin; | |
private Gpio mMisoPin; | |
public MCP3008(String csPin, String clockPin, String mosiPin, String misoPin) { | |
this.csPin = csPin; | |
this.clockPin = clockPin; | |
this.mosiPin = mosiPin; | |
this.misoPin = misoPin; | |
} | |
public void register() throws IOException { | |
PeripheralManagerService service = new PeripheralManagerService(); | |
mClockPin = service.openGpio(clockPin); | |
mCsPin = service.openGpio(csPin); | |
mMosiPin = service.openGpio(mosiPin); | |
mMisoPin = service.openGpio(misoPin); | |
mClockPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); | |
mCsPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); | |
mMosiPin.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); | |
mMisoPin.setDirection(Gpio.DIRECTION_IN); | |
} | |
public int readAdc(int channel) throws IOException { | |
if (channel < 0 || channel > 7) { | |
throw new IOException("ADC channel must be between 0 and 7"); | |
} | |
initReadState(); | |
initChannelSelect(channel); | |
return getValueFromSelectedChannel(); | |
} | |
private int getValueFromSelectedChannel() throws IOException { | |
int value = 0x0; | |
for (int i = 0; i < 12; i++) { | |
toggleClock(); | |
value <<= 0x1; | |
if (mMisoPin.getValue()) { | |
value |= 0x1; | |
} | |
} | |
mCsPin.setValue(true); | |
value >>= 0x1; // first bit is 'null', so drop it | |
return value; | |
} | |
private void initReadState() throws IOException { | |
mCsPin.setValue(true); | |
mClockPin.setValue(false); | |
mCsPin.setValue(false); | |
} | |
private void initChannelSelect(int channel) throws IOException { | |
int commandout = channel; | |
commandout |= 0x18; // start bit + single-ended bit | |
commandout <<= 0x3; // we only need to send 5 bits | |
for (int i = 0; i < 5; i++) { | |
if ((commandout & 0x80) != 0x0) { | |
mMosiPin.setValue(true); | |
} else { | |
mMosiPin.setValue(false); | |
} | |
commandout <<= 0x1; | |
toggleClock(); | |
} | |
} | |
private void toggleClock() throws IOException { | |
mClockPin.setValue(true); | |
mClockPin.setValue(false); | |
} | |
public void unregister() { | |
if (mCsPin != null) { | |
try { | |
mCsPin.close(); | |
} catch (IOException ignore) { | |
// do nothing | |
} | |
} | |
if (mClockPin != null) { | |
try { | |
mClockPin.close(); | |
} catch (IOException ignore) { | |
// do nothing | |
} | |
} | |
if (mMisoPin != null) { | |
try { | |
mMisoPin.close(); | |
} catch (IOException ignore) { | |
// do nothing | |
} | |
} | |
if (mMosiPin != null) { | |
try { | |
mMosiPin.close(); | |
} catch (IOException ignore) { | |
// do nothing | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment