diff --git a/README.md b/README.md index 754d243ca..db13866a2 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,50 @@ Sign up for the latest updates and test new features early by joining our beta p | Gas Sensor | Detects gases, including NH3, NOx, alcohol, benzene, smoke and CO2| :heavy_check_mark: | | Robotic Arm Controller | Allows to control 4 servo motors of the robotic arm independently | :heavy_check_mark: | +## Robotic Arm Control + +The Robotic Arm feature in the PSLab Android app allows users to control a servo-based robotic arm using the Pocket Science Lab hardware. This is ideal for educational robotics, DIY automation, and remote experiments. + +# Key Capabilities + +-Manual control of servo motors using sliders. + +-Set angles precisely for each servo. + +-Create custom movement profiles (position sets). + +-Save/load profiles from local storage using internal database. + +-Export/import profiles in JSON format. + +-Replay saved profiles for automation. + +# How to Use the Robotic Arm Screen + +-Connect the PSLab device via USB. + +-Go to Instruments > Robotic Arm. + +-Use the sliders to move each servo (e.g., Base, Shoulder, Elbow, Gripper). + +-Set desired positions for all servos. + +-Tap Save Profile to store the current servo positions. + +-Use Load Profile to retrieve saved movements. + +-Tap Play to replay the selected profile. + +# Saving and Loading Profiles + +-Save: Stores the current servo angles into a named profile in local database. + +-Load: Loads the servo angles from a selected profile and updates the UI. + +-Export: Saves profile(s) to a .json file. + +-Import: Load external JSON files to restore or share profiles. + ## How to set up the Android app in your development environment ### Application Flavors diff --git a/app/src/main/java/io/pslab/activity/CreateConfigActivity.java b/app/src/main/java/io/pslab/activity/CreateConfigActivity.java index 388692c5b..64229e3fc 100644 --- a/app/src/main/java/io/pslab/activity/CreateConfigActivity.java +++ b/app/src/main/java/io/pslab/activity/CreateConfigActivity.java @@ -159,7 +159,12 @@ private void createCheckboxList() { @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { - finish(); + finish();rea + }else if (item.getItemId() == R.id.compass_help_icon) { + + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://your-documentation-link.com")); + startActivity(browserIntent); + return true; } return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/io/pslab/activity/RoboticArmActivity.java b/app/src/main/java/io/pslab/activity/RoboticArmActivity.java index 4a6b8a5de..ca1c60b08 100644 --- a/app/src/main/java/io/pslab/activity/RoboticArmActivity.java +++ b/app/src/main/java/io/pslab/activity/RoboticArmActivity.java @@ -225,13 +225,20 @@ protected void onCreate(Bundle savedInstanceState) { seekArc1.setOnSeekArcChangeListener(new SeekArc.OnSeekArcChangeListener() { @Override public void onProgressChanged(SeekArc seekArc, int i, boolean b) { + int angle; if (editEnter) { + angle = degree; degreeText1.setText(String.valueOf(degree)); editEnter = false; } else { + angle = (int) (i * 3.6); degreeText1.setText(String.valueOf((int) (i * 3.6))); } degreeText1.setCursorVisible(false); + + if (scienceLab != null && scienceLab.isConnected()) { + scienceLab.servoWrite(0, angle); + } } @Override @@ -248,13 +255,19 @@ public void onStopTrackingTouch(SeekArc seekArc) { seekArc2.setOnSeekArcChangeListener(new SeekArc.OnSeekArcChangeListener() { @Override public void onProgressChanged(SeekArc seekArc, int i, boolean b) { + int angle; if (editEnter) { + angle = degree; degreeText2.setText(String.valueOf(degree)); editEnter = false; } else { + angle = (int) (i * 3.6); degreeText2.setText(String.valueOf((int) (i * 3.6))); } degreeText2.setCursorVisible(false); + if (scienceLab != null && scienceLab.isConnected()) { + scienceLab.servoWrite(1, angle); + } } @Override @@ -271,13 +284,19 @@ public void onStopTrackingTouch(SeekArc seekArc) { seekArc3.setOnSeekArcChangeListener(new SeekArc.OnSeekArcChangeListener() { @Override public void onProgressChanged(SeekArc seekArc, int i, boolean b) { + int angle; if (editEnter) { + angle = degree; degreeText3.setText(String.valueOf(degree)); editEnter = false; } else { + angle = (int) (i * 3.6); degreeText3.setText(String.valueOf((int) (i * 3.6))); } degreeText3.setCursorVisible(false); + if (scienceLab != null && scienceLab.isConnected()) { + scienceLab.servoWrite(2, angle); + } } @Override @@ -294,13 +313,19 @@ public void onStopTrackingTouch(SeekArc seekArc) { seekArc4.setOnSeekArcChangeListener(new SeekArc.OnSeekArcChangeListener() { @Override public void onProgressChanged(SeekArc seekArc, int i, boolean b) { + int angle; if (editEnter) { + angle = degree; degreeText4.setText(String.valueOf(degree)); editEnter = false; } else { + angle = (int) (i * 3.6); degreeText4.setText(String.valueOf((int) (i * 3.6))); } degreeText4.setCursorVisible(false); + if (scienceLab != null && scienceLab.isConnected()) { + scienceLab.servoWrite(3, angle); + } } @Override diff --git a/app/src/main/java/io/pslab/activity/SensorActivity.java b/app/src/main/java/io/pslab/activity/SensorActivity.java index 5e9021968..ea2d1ffcf 100644 --- a/app/src/main/java/io/pslab/activity/SensorActivity.java +++ b/app/src/main/java/io/pslab/activity/SensorActivity.java @@ -78,7 +78,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { sensorAddr.put(0x77, "BMP180"); sensorAddr.put(0x5A, "MLX90614"); sensorAddr.put(0x1E, "HMC5883L"); - sensorAddr.put(0x68, "MPU6050"); + sensorAddr.put(0x69, "MPU6050"); sensorAddr.put(0x40, "SHT21"); sensorAddr.put(0x39, "TSL2561"); sensorAddr.put(0x69, "MPU925x"); diff --git a/app/src/main/java/io/pslab/activity/SensorDataLoggerActivity.java b/app/src/main/java/io/pslab/activity/SensorDataLoggerActivity.java index d71c61681..f85434940 100644 --- a/app/src/main/java/io/pslab/activity/SensorDataLoggerActivity.java +++ b/app/src/main/java/io/pslab/activity/SensorDataLoggerActivity.java @@ -149,7 +149,7 @@ public void onItemClick(AdapterView parent, View view, int position, long id) sensorAddress.put(0x77, "BMP180"); sensorAddress.put(0x5A, "MLX90614"); sensorAddress.put(0x1E, "HMC5883L"); - sensorAddress.put(0x68, "MPU6050"); + sensorAddress.put(0x69, "MPU6050"); sensorAddress.put(0x40, "SHT21"); sensorAddress.put(0x39, "TSL2561"); } diff --git a/app/src/main/java/io/pslab/activity/SettingsActivity.java b/app/src/main/java/io/pslab/activity/SettingsActivity.java index c718484ae..6b620300f 100644 --- a/app/src/main/java/io/pslab/activity/SettingsActivity.java +++ b/app/src/main/java/io/pslab/activity/SettingsActivity.java @@ -57,6 +57,14 @@ protected void onCreate(Bundle savedInstanceState) { actionBar.setTitle(title); } + Button myButton = findViewById(R.id.myButton); + myButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Toast.makeText(CompassActivity.this, "Button clicked!", Toast.LENGTH_SHORT).show(); + } + }); + Fragment fragment; switch (title) { case PSLabSensor.LUXMETER_CONFIGURATIONS: @@ -95,12 +103,29 @@ protected void onCreate(Bundle savedInstanceState) { getSupportFragmentManager().beginTransaction().add(R.id.content, fragment).commit(); } } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.activity_compass_help_menu, menu); + return true; + } @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - finish(); - } + int id = item.getItemId(); + + if (id == android.R.id.home) { + finish(); + return true; + } else if (id == R.id.compass_record_data) { + + Toast.makeText(this, "Recording current compass data...", Toast.LENGTH_SHORT).show(); + return true; + } else if (id == R.id.compass_help_icon) { + + Toast.makeText(this, "Opening compass help...", Toast.LENGTH_SHORT).show(); + return true; + } + return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/io/pslab/communication/SensorList.java b/app/src/main/java/io/pslab/communication/SensorList.java index 2ff102ba5..2d89dcb89 100644 --- a/app/src/main/java/io/pslab/communication/SensorList.java +++ b/app/src/main/java/io/pslab/communication/SensorList.java @@ -25,7 +25,7 @@ public SensorList() { sensorList.put(0x5A, new String[]{"MLX90614 PIR temperature"}); sensorList.put(0x1E, new String[]{"HMC5883L magnetometer", "LSM303 magnetometer"}); sensorList.put(0x77, new String[]{"BMP180/GY-68 altimeter", "MS5607", "MS5611"}); - sensorList.put(0x68, new String[]{"MPU-6050/GY-521 accel+gyro+temp", "ITG3200", "DS1307", "DS3231"}); + sensorList.put(0x69, new String[]{"MPU-6050/GY-521 accel+gyro+temp", "ITG3200", "DS1307", "DS3231"}); sensorList.put(0x69, new String[]{"ITG3200"}); sensorList.put(0x76, new String[]{"MS5607", "MS5611"}); sensorList.put(0x6B, new String[]{"LSM9DSO gyro"}); diff --git a/app/src/main/java/io/pslab/communication/sensors/MPU6050.java b/app/src/main/java/io/pslab/communication/sensors/MPU6050.java index ed286632e..af0cf2b27 100644 --- a/app/src/main/java/io/pslab/communication/sensors/MPU6050.java +++ b/app/src/main/java/io/pslab/communication/sensors/MPU6050.java @@ -25,7 +25,7 @@ public class MPU6050 { private int GR = 3; private int NUMPLOTS = 7; public String[] PLOTNAMES = {"Ax", "Ay", "Az,'Temp", "Gx", "Gy", "Gz"}; - private int ADDRESS = 0x68; + private int ADDRESS = 0x69; private String name = "Accel/gyro"; private ArrayList K = new ArrayList<>(); //K is the list of KalmanFilter object private I2C i2c; diff --git a/app/src/main/java/io/pslab/communication/sensors/MPU925x.java b/app/src/main/java/io/pslab/communication/sensors/MPU925x.java index f26bd6ea9..e7ca7af99 100644 --- a/app/src/main/java/io/pslab/communication/sensors/MPU925x.java +++ b/app/src/main/java/io/pslab/communication/sensors/MPU925x.java @@ -27,7 +27,7 @@ public class MPU925x { private int GR = 3; private int NUMPLOTS = 7; public String[] PLOTNAMES = new String[]{"Ax", "Ay", "Az", "Temp", "Gx", "Gy", "Gz"}; - private int ADDRESS = 0x68; + private int ADDRESS = 0x69; private int AK8963_ADDRESS = 0x0C; private int AK8963_CNTL = 0x0A; public String name = "Accel/gyro"; diff --git a/app/src/main/java/io/pslab/fragment/AccelerometerDataFragment.java b/app/src/main/java/io/pslab/fragment/AccelerometerDataFragment.java index 197910e0a..789909742 100644 --- a/app/src/main/java/io/pslab/fragment/AccelerometerDataFragment.java +++ b/app/src/main/java/io/pslab/fragment/AccelerometerDataFragment.java @@ -417,6 +417,9 @@ private void writeLogToFile(long timestamp, float readingX, float readingY, floa accelerometerSensor.writeHeaderToFile = true; } } + public LineChart getChart() { + return chart; + } private void visualizeData() { for (int i = 0; i < accelerometerViewFragments.size(); i++) { @@ -435,7 +438,16 @@ private void visualizeData() { LineData data = new LineData(dataSet); fragment.setChartData(data); + fragment.setYaxis(highLimit); + // ✅ Auto-scaling Y-axis + LineChart chart = fragment.getChart(); // Assuming you have this getter method + chart.setAutoScaleMinMaxEnabled(true); + chart.getAxisLeft().resetAxisMaximum(); + chart.getAxisLeft().resetAxisMinimum(); + + chart.notifyDataSetChanged(); + chart.invalidate(); } } Long currentTime = System.currentTimeMillis(); diff --git a/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java b/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java index 6238e1c88..fb1c15dfc 100644 --- a/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java +++ b/app/src/main/java/io/pslab/fragment/BaroMeterDataFragment.java @@ -112,8 +112,6 @@ private enum BARO_SENSOR {INBUILT_SENSOR, BMP180_SENSOR} private ArrayList altitudeEntries; private ArrayList recordedBaroArray; private BaroData sensorData; - private float currentMin = 2; - private float currentMax = 0.5f; private YAxis y; private YAxis y2; private Unbinder unbinder; @@ -166,12 +164,18 @@ public void onResume() { updateGraphs(); sum = 0; count = 0; - currentMin = 2; - currentMax = 0.5f; + // REMOVE these fixed axis values to allow auto-scaling + // currentMin = 2; + // currentMax = 0.5f; pressureEntries.clear(); altitudeEntries.clear(); mChart.clear(); mChart.invalidate(); + // Auto-scaling: reset min/max if using MPAndroidChart + mChart.getAxisLeft().resetAxisMinimum(); + mChart.getAxisLeft().resetAxisMaximum(); + mChart.getAxisRight().resetAxisMinimum(); + mChart.getAxisRight().resetAxisMaximum(); initiateBaroSensor(sensorType); } else if (returningFromPause) { updateGraphs(); diff --git a/app/src/main/java/io/pslab/fragment/GyroscopeDataFragment.java b/app/src/main/java/io/pslab/fragment/GyroscopeDataFragment.java index 68de4b1e1..3fc67b587 100644 --- a/app/src/main/java/io/pslab/fragment/GyroscopeDataFragment.java +++ b/app/src/main/java/io/pslab/fragment/GyroscopeDataFragment.java @@ -423,6 +423,9 @@ private void writeLogToFile(long timestamp, float readingX, float readingY, floa gyroSensor.writeHeaderToFile = true; } } + public LineChart getChart() { + return chart; // Make sure your LineChart variable is named 'chart' + } private void visualizeData() { for (int i = 0; i < gyroscopeViewFragments.size(); i++) { @@ -441,7 +444,17 @@ private void visualizeData() { LineData data = new LineData(dataSet); fragment.setChartData(data); - fragment.setYaxis(highLimit); + // REMOVE this line as it is forcing fixed Y-axis: + // fragment.setYaxis(highLimit); + + // NEW: Enable auto-scaling + LineChart chart = fragment.getChart(); + chart.setAutoScaleMinMaxEnabled(true); + chart.getAxisLeft().resetAxisMaximum(); + chart.getAxisLeft().resetAxisMinimum(); + + chart.notifyDataSetChanged(); + chart.invalidate(); } } Long currentTime = System.currentTimeMillis(); diff --git a/app/src/main/java/io/pslab/fragment/LuxMeterDataFragment.java b/app/src/main/java/io/pslab/fragment/LuxMeterDataFragment.java index adcccfe11..74f155016 100644 --- a/app/src/main/java/io/pslab/fragment/LuxMeterDataFragment.java +++ b/app/src/main/java/io/pslab/fragment/LuxMeterDataFragment.java @@ -109,8 +109,6 @@ private enum LUX_SENSOR {INBUILT_SENSOR, BH1750_SENSOR, TSL2561_SENSOR} private ArrayList entries; private ArrayList recordedLuxArray; private LuxData sensorData; - private float currentMin = 10000; - private float currentMax = 0; private YAxis y; private Unbinder unbinder; private long previousTimeElapsed = (System.currentTimeMillis() - startTime) / updatePeriod; @@ -162,11 +160,18 @@ public void onResume() { updateGraphs(); sum = 0; count = 0; - currentMin = 10000; - currentMax = 0; + // REMOVE these fixed axis values to allow auto-scaling + // currentMin = 10000; + // currentMax = 0; entries.clear(); mChart.clear(); mChart.invalidate(); + // Auto-scaling: reset min/max if using MPAndroidChart + mChart.getAxisLeft().resetAxisMinimum(); + mChart.getAxisLeft().resetAxisMaximum(); + mChart.getAxisRight().resetAxisMinimum(); + mChart.getAxisRight().resetAxisMaximum(); + initiateBaroSensor(sensorType); initiateLuxSensor(sensorType); } else if (returningFromPause) { updateGraphs(); diff --git a/app/src/main/java/io/pslab/fragment/ThermometerDataFragment.java b/app/src/main/java/io/pslab/fragment/ThermometerDataFragment.java index 7005352a0..c7fb8b73f 100644 --- a/app/src/main/java/io/pslab/fragment/ThermometerDataFragment.java +++ b/app/src/main/java/io/pslab/fragment/ThermometerDataFragment.java @@ -108,8 +108,6 @@ private enum THERMOMETER_SENSOR {INBUILT_SENSOR, SHT21_SENSOR} private ArrayList entries; private ArrayList recordedThermoArray; private ThermometerData sensorData; - private float currentMin = 125; - private float currentMax = -40; private YAxis y; private Unbinder unbinder; private long previousTimeElapsed = (System.currentTimeMillis() - startTime) / updatePeriod; @@ -166,6 +164,13 @@ public void onResume() { entries.clear(); mChart.clear(); mChart.invalidate(); + // Auto-scaling: reset min/max if using MPAndroidChart + mChart.getAxisLeft().resetAxisMinimum(); + mChart.getAxisLeft().resetAxisMaximum(); + mChart.getAxisRight().resetAxisMinimum(); + mChart.getAxisRight().resetAxisMaximum(); + initiateBaroSensor(sensorType); + initiateLuxSensor(sensorType); initiateThermoSensor(sensorType); } else if (returningFromPause) { updateGraphs(); diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 3b86bf742..92cfadef9 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -10,6 +10,7 @@ توصيل الجهاز الادوات الإعدادات + التوثيق معلومات عنا شراء PSLab ردود الفعل @@ -284,6 +285,18 @@ GX Gy Gz + أحمر + أخضر + أزرق + مسح + إيماءة + ثاني أكسيد الكربون المكافئ + المركبات العضوية المتطايرة الكلية + مخطط - ضوء لوكس + مخطط - القرب + القرب + لوكس + لوكس مؤقت لمعان رطوبة diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 61363df69..36ab1b534 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -10,6 +10,7 @@ Połącz urządzenie Narzędzia Ustawienia + Dokumentacja O nas Kup PSLab Opinie & Błędy @@ -287,6 +288,18 @@ Gx Gy Gz + Czerwony + Zielony + Niebieski + Wyczyść + Gest + eCO2 + TVOC + Wykres - Natężenie światła + Wykres - Bliskość + Bliskość + lx + Luks Temp Luminancja Wilgotność diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index e7ea2395b..91a4dff0a 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -10,6 +10,7 @@ Подключение устройства Инструменты Settings + Документация О нас Купить PSLab Обратная связь @@ -288,6 +289,18 @@ Gx Gy Gz + Красный + Зелёный + Синий + Очистить + Жест + eCO2 + TVOC + График - Освещённость (Lux) + График - Близость + Близость + lx + Люкс Температуры Светимость Влажность diff --git a/app/src/main/res/values-si/string.xml b/app/src/main/res/values-si/string.xml index 73618b476..027f74e01 100644 --- a/app/src/main/res/values-si/string.xml +++ b/app/src/main/res/values-si/string.xml @@ -10,6 +10,7 @@ උපාංගය සම්බන්ධ කරන්න උපකරණ සැකසුම් + ලේඛන ගබඩාව අප ගැන PSLab මිලදී ගන්න දෝෂ හා ප්‍රතිචාර @@ -288,6 +289,18 @@ Gx Gy Gz + රතු + කොළ + නීල + මකන්න + ඉඟිය + eCO2 + TVOC + ප්ලොට් - ආලෝක ලක්ෂ + ප්ලොට් - සමීපත්වය + සමීපත්වය + lx + ලක්ස් උෂ්ණත්වය ආලෝක තීව්‍රතාවය ආර්ද්‍රතාවය diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1de834d4f..e9e35f1a7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -302,7 +302,7 @@ Plot - Light Lux Plot - Proximity Prox - (lx) + lx Lux Temp Luminosity