Video hướng dẫn mạch bơm nước tự động
Thứ Năm, 28 tháng 3, 2019
mạch bơm nước tự động
Google Account Video Purchases
Hồ Chí Minh, Việt Nam
Thứ Ba, 26 tháng 3, 2019
Điện tử
Hướng dẫn làm lo cảm ứng từ lo thường
VIDEO HƯỚNG DẪN LÀM LO CẢM ỨNG
VIDEO HƯỚNG DẪN LÀM LO CẢM ỨNG
Google Account Video Purchases
Đồng bằng Sông Cửu Long, Việt Nam
Thứ Năm, 12 tháng 4, 2018
PHẦN MỀM QUAy PHIM MÀN HÌNH MÁY TÍNH
Mình xin chia sẻ với các bạn phần mềm quay phim màn hình máy tính cực kỳ nhẹ luôn chạy rất ngon
các bạn vào đây down về mà dùng nha: DOWNLOAD
các bạn vào đây down về mà dùng nha: DOWNLOAD
Thứ Tư, 11 tháng 4, 2018
CODE UPLOAD FILE LEN GOOGLE DRIVE
Code tạo nút nhấn upload file lên google drive
xem video rồi làm theo nha:
Đàu tiên ta mở google lên rồi đăng nhập vào tài khoản google mà ta có
sau đó vào trang này: NHẤP VÀO ĐÂY
chọn vào menu:Tệp→Mới→Dự án .ta chọn mục: Dự án một giao diện mới hiện ra như hình:
Chú ý trong cái khung hình vuông viền bao màu đỏ (nếu có bất cứ chữ gì thì hãy xóa bỏ hết đi đê ta viết đoạn code mới của ta vào:
chúng ta bắt dầu copy và dán đoạn code dưới đây vào cái khung viền mực màu đỏ đó:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function uploadFiles(form) {
try {
var dropbox = "Student Files";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var blob = form.myFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
return "File uploaded successfully " + file.getUrl();
} catch (error) {
return error.toString();
}
}
tiếp tục làm như hình:
đổi tên Mã.gs thành tên server.gs như hình:
Tiếp tục làm theo hình:
ta đưa chuột tới Tệp→Mới→Tệp Html và nhắp chuột chọn mục Tệp Html
một giao diện như hình mở ra:
ta đặt tên cho nó là form.html như hình dưới:
xong bấm Ok .Một giao diện mới hiện ra như hình dưới:
copy và dán đoạn code dưới đây vào khung viền màu đỏ:
<!--
S U P P O R T
- - - - - - -
Web: ctrlq.org
Twitter: @labnol
Email: amit@labnol.org
-->
<form id="myForm">
<input type="text" name="myName" placeholder="Your name..">
<input type="file" name="myFile">
<input type="submit" value="Upload File"
onclick="this.value='Uploading..';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;">
</form>
<div id="output"></div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
tiếp tục làm như hình:
và:
tiếp tục
tiếp
tiếp tục
xong rồi đó như vậy sau khi copy đường link như hình trên và ta chia sẽ cho những ai muốn upload file vào google drive cua ta.
Chú Ý: dữ liệu sau khi upload sẽ vào nằm trong thư mục:Student Files
ta vào thư mục đó để xem
xem video rồi làm theo nha:
Đàu tiên ta mở google lên rồi đăng nhập vào tài khoản google mà ta có
sau đó vào trang này: NHẤP VÀO ĐÂY
chọn vào menu:Tệp→Mới→Dự án .ta chọn mục: Dự án một giao diện mới hiện ra như hình:
Chú ý trong cái khung hình vuông viền bao màu đỏ (nếu có bất cứ chữ gì thì hãy xóa bỏ hết đi đê ta viết đoạn code mới của ta vào:
chúng ta bắt dầu copy và dán đoạn code dưới đây vào cái khung viền mực màu đỏ đó:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function uploadFiles(form) {
try {
var dropbox = "Student Files";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var blob = form.myFile;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
return "File uploaded successfully " + file.getUrl();
} catch (error) {
return error.toString();
}
}
tiếp tục làm như hình:
đổi tên Mã.gs thành tên server.gs như hình:
Tiếp tục làm theo hình:
ta đưa chuột tới Tệp→Mới→Tệp Html và nhắp chuột chọn mục Tệp Html
một giao diện như hình mở ra:
ta đặt tên cho nó là form.html như hình dưới:
xong bấm Ok .Một giao diện mới hiện ra như hình dưới:
copy và dán đoạn code dưới đây vào khung viền màu đỏ:
<!--
S U P P O R T
- - - - - - -
Web: ctrlq.org
Twitter: @labnol
Email: amit@labnol.org
-->
<form id="myForm">
<input type="text" name="myName" placeholder="Your name..">
<input type="file" name="myFile">
<input type="submit" value="Upload File"
onclick="this.value='Uploading..';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;">
</form>
<div id="output"></div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
tiếp tục làm như hình:
và:
tiếp tục
tiếp
tiếp tục
xong rồi đó như vậy sau khi copy đường link như hình trên và ta chia sẽ cho những ai muốn upload file vào google drive cua ta.
Chú Ý: dữ liệu sau khi upload sẽ vào nằm trong thư mục:Student Files
ta vào thư mục đó để xem
Google drive download one click
CÁCH DOWNLOAD TỪ GOOGLE DRIVE CHỈ VỚI MỘT CLICK
(hay còn gọi là:direct Link)
Đầu tiên xem video hướng dẫn và ta làm theo nhé
Nào bây giờ chúng ta bắt tay vào lám nhé:
Đầu tiên chúng ta đăng nhập vào google drive
tiếp đến ta chọn một file mà ta cần chia sẻ
và nháp vào mục chia sẻ để lấy link chia sẻ,ví dụ ở đây tôi có một link mà tôi cần chia sẻ là:
https://drive.google.com/file/d/1GvkjumUTn-FJw67w1gL8r1XH3tEfnAc2/view?usp=sharing
chúng ta chọn cái hàng chữ màu đỏ trong đường link trên ,sau đó copy cái hàng chữ màu đỏ đó
và dán phía sau cùng đường link mới dưới đây(chú ý dán vào phía sau dấu = trở đi nha) :
https://docs.google.com/uc?export=download&id=
và kết quả ta được một đường link mới như sau:
https://docs.google.com/uc?export=download&id=1GvkjumUTn-FJw67w1gL8r1XH3tEfnAc2
chúng ta copy đường link mới tạo này dán vào khung tìm kiếm của trình duyệt web và nhấn enter
thì tập tin của chúng ta sẽ được download về máy tính một cách tự động (chứ không phải qua nhiều bước dài dòng nữa)
(điều này chúng ta có thể áp dụng để tạo một nút nhấn download cho web hoặc blog chỉ với một click chuột rồi đó).Chúc các bạn thành công.tạm biệt
(hay còn gọi là:direct Link)
Đầu tiên xem video hướng dẫn và ta làm theo nhé
Nào bây giờ chúng ta bắt tay vào lám nhé:
Đầu tiên chúng ta đăng nhập vào google drive
tiếp đến ta chọn một file mà ta cần chia sẻ
và nháp vào mục chia sẻ để lấy link chia sẻ,ví dụ ở đây tôi có một link mà tôi cần chia sẻ là:
https://drive.google.com/file/d/1GvkjumUTn-FJw67w1gL8r1XH3tEfnAc2/view?usp=sharing
chúng ta chọn cái hàng chữ màu đỏ trong đường link trên ,sau đó copy cái hàng chữ màu đỏ đó
và dán phía sau cùng đường link mới dưới đây(chú ý dán vào phía sau dấu = trở đi nha) :
https://docs.google.com/uc?export=download&id=
và kết quả ta được một đường link mới như sau:
https://docs.google.com/uc?export=download&id=1GvkjumUTn-FJw67w1gL8r1XH3tEfnAc2
chúng ta copy đường link mới tạo này dán vào khung tìm kiếm của trình duyệt web và nhấn enter
thì tập tin của chúng ta sẽ được download về máy tính một cách tự động (chứ không phải qua nhiều bước dài dòng nữa)
(điều này chúng ta có thể áp dụng để tạo một nút nhấn download cho web hoặc blog chỉ với một click chuột rồi đó).Chúc các bạn thành công.tạm biệt
WEB TẢI APK VỀ PC
Các bạn vào trang này để tải các ứng dụng từ CH PLAY về PC nhé
NHẤP VÀO ĐÂY
Dùng android để điều khiển youtube thông qua Android Tivi box
nếu nhà bạn đang có một chiếc Android Tivi box thì các bạn có thể làm theo cách này để dùng điện thoại của bạn điều khiển youtube trên chiếc android tivi box đó cái này dùng để karaoke thì khỏi chê
đầu tiên ta vào đây tải file Apk này về cài lên điện thoại và lên cả chiếc Android tivi box luôn nha: DOWNLOAD
sau đó mở phần mềm này lên trên điện thoại và trên chiếc android tivi box cũng phải mở lên luôn nha và cả hai diều kết nối cùng một mạng Wifi mới được nha
xong rồi ta tiến hành thiết lập kết nối (chú ý ở đây ta chỉ thiết lập một lần và sau đó nó sẻ tự nhớ luôn mà không cần thiết lập lại nữa)
trên điện thoại ta chọn chế độ là remote còn trên Tivi ta chọn chế độ Television(tức là chế độ Tivi đó)
xong rồi đó vậy bây giờ bạn chỉ việc tìm kiếm trên điện thoại và nọi dung tiềm kiếm sẽ tự động hiển thị trên Tivi nha .có nhiều chức năng lắm giống như đầu karaoke6 vậy các bạn tự mò thêm nha .Tạm biệt
Phần mềm: Remote Shutter Camera.Apk
Các bạn vào đây down nhé ,xong cài đặt lên Android và sử dụng nhé : DOWNLOAD
dùng một cái loa bluetooth kết nối với điện thoại xong mở phần mềm này lên và thiết lập để cho nó học các nút nhấn trên loa để làm các nhiệm vụ chụp ảnh ví dụ như nút tăng âm lượng trên loa trở thành để chụp ảnh ,nút trừ âm lượng trên loa thành nút Zoom camera trên điện thoại chẳng hạn vv.... các bạn tự mò thêm,mình chỉ ví dụ hai nút cho dễ hiểu.Tạm biệt
NHẤP VÀO ĐÂY
Dùng android để điều khiển youtube thông qua Android Tivi box
nếu nhà bạn đang có một chiếc Android Tivi box thì các bạn có thể làm theo cách này để dùng điện thoại của bạn điều khiển youtube trên chiếc android tivi box đó cái này dùng để karaoke thì khỏi chê
đầu tiên ta vào đây tải file Apk này về cài lên điện thoại và lên cả chiếc Android tivi box luôn nha: DOWNLOAD
sau đó mở phần mềm này lên trên điện thoại và trên chiếc android tivi box cũng phải mở lên luôn nha và cả hai diều kết nối cùng một mạng Wifi mới được nha
xong rồi ta tiến hành thiết lập kết nối (chú ý ở đây ta chỉ thiết lập một lần và sau đó nó sẻ tự nhớ luôn mà không cần thiết lập lại nữa)
trên điện thoại ta chọn chế độ là remote còn trên Tivi ta chọn chế độ Television(tức là chế độ Tivi đó)
xong rồi đó vậy bây giờ bạn chỉ việc tìm kiếm trên điện thoại và nọi dung tiềm kiếm sẽ tự động hiển thị trên Tivi nha .có nhiều chức năng lắm giống như đầu karaoke6 vậy các bạn tự mò thêm nha .Tạm biệt
Phần mềm: Remote Shutter Camera.Apk
Các bạn vào đây down nhé ,xong cài đặt lên Android và sử dụng nhé : DOWNLOAD
dùng một cái loa bluetooth kết nối với điện thoại xong mở phần mềm này lên và thiết lập để cho nó học các nút nhấn trên loa để làm các nhiệm vụ chụp ảnh ví dụ như nút tăng âm lượng trên loa trở thành để chụp ảnh ,nút trừ âm lượng trên loa thành nút Zoom camera trên điện thoại chẳng hạn vv.... các bạn tự mò thêm,mình chỉ ví dụ hai nút cho dễ hiểu.Tạm biệt
Thứ Ba, 10 tháng 4, 2018
ARDUINO BAI 2
Bài này mình sẻ nói về cảm biến 6 trục: MPU-6050 gyro
Vào đây để down thư viện của nó: DOWNLOAD và thư viện I2C: DOWNLOAD
Add 2 thư viện trên vào trình soạn thảo Arduino rồi xem video này trước khi bắt tay vào làm
Bây giờ ta down code nay về và dán vào trình soạn thảo Arduino tiếp đến nạp vào board Arduino rồi lắp mạch như trong Video rồi cấp nguồn cho chạy thử
Vào đây down code arduino: DOWNLOAD
hoặc có thể chép trực tiếp ở đây rồi dán vào trình soạn thảo Arduino:
Đoạn code của nó là:
/**
* Simple implementation false
* means that for pitch/yaw there only be
* a single led for each direction. The led will get more bright
* as the direction increases
* Simple implementation true
* means that for pitch/yaw there will be multiple led's that light up one by one
* The accelerometer/gyro is a MPU6050, it should be wired to the SDA and SCL pins
*/
#define SIMPLE_IMPLEMENTATION false
const int frontLed = 3;
const int bottomLed = 5;
const int rightLed = 6;
const int leftLed = 9;
long int lastPrintTime;
typedef struct
{
byte pin;
byte positionInsideGroup;
char thePosition; // Left, Right, Up, Down
byte minAngle;
byte maxAngle;
} ledConfig;
ledConfig leds[] = {
{3, 1, 'u', 31, 45},
{12, 2, 'u', 16, 30},
{11, 3, 'u', 5, 15},
{5, 1, 'd', 5, 15},
{6, 2, 'd', 16, 30},
{7, 3, 'd', 31, 45},
{8 , 1, 'r', 5, 23},
{9, 2, 'r', 24, 45},
{10, 1, 'l', 5, 23},
{4, 2, 'l', 24, 45},
};
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void setup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(9600);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
if (SIMPLE_IMPLEMENTATION) {
initializeLEDsSimple();
} else {
initializeLEDsMultiple();
}
lastPrintTime = millis();
}
void loop()
{
if (!dmpReady) return;
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
} else if (mpuIntStatus & 0x02) {
while (fifoCount < packetSize) {
fifoCount = mpu.getFIFOCount();
}
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
int x = ypr[0] * 180/M_PI;
int y = ypr[1] * 180/M_PI;
int z = ypr[2] * 180/M_PI;
Serial.print(y);Serial.print("\t");Serial.println(z);
if (SIMPLE_IMPLEMENTATION) {
flashLEDsSimple(x, y, z);
} else {
flashLEDsMultiple(x, y, z);
}
}
}
void initializeLEDsSimple()
{
pinMode(frontLed, OUTPUT);
pinMode(bottomLed, OUTPUT);
pinMode(rightLed, OUTPUT);
pinMode(leftLed, OUTPUT);
}
void initializeLEDsMultiple()
{
for (int i=0; i<10; i++) {
Serial.println(leds[i].pin);
pinMode(leds[i].pin, OUTPUT);
}
delay(3000);
}
void flashLEDsSimple(int x, int y, int z)
{
if (y > 0) {
analogWrite(rightLed, y*4);
analogWrite(leftLed, 0);
} else {
analogWrite(leftLed, y*4*-1);
analogWrite(rightLed, 0);
}
if (z > 0) {
analogWrite(bottomLed, z*4);
analogWrite(frontLed, 0);
} else {
analogWrite(frontLed, z*4*-1);
analogWrite(bottomLed, 0);
}
}
void flashLEDsMultiple(int x, int y, int z)
{
for (int i=0; i<10; i++) {
//Serial.print(z);Serial.print(",");Serial.print(leds[i].thePosition);Serial.print(",");Serial.println(leds[i].minAngle);
bool modified = false;
if (z < 0 && leds[i].thePosition == 'u' && abs(z) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (z > 0 && leds[i].thePosition == 'd' && abs(z) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (y < 0 && leds[i].thePosition == 'l' && abs(y) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (y > 0 && leds[i].thePosition == 'r' && abs(y) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (!modified) {
digitalWrite(leds[i].pin, LOW);
}
}
}
void dmpDataReady()
{
mpuInterrupt = true;
}
Vậy là ta đã hoàn thành một ví dụ rồi đó.
ta xem tiếp tục một ví dụ về cảm biến 6 trục nửa nha
Và đây là video cách vận hành của nó:
Và đây là Full code của nó:
/**
* Simple implementation false
* means that for pitch/yaw there only be
* a single led for each direction. The led will get more bright
* as the direction increases
*
* Simple implementation true
* means that for pitch/yaw there will be multiple led's that light up one by one
* The accelerometer is a MPU6050, it should be wired to the SDA and SCL pins
*/
#define SIMPLE_IMPLEMENTATION true
const int frontLed = 3;
const int bottomLed = 5;
const int rightLed = 6;
const int leftLed = 9;
long int lastPrintTime;
typedef struct
{
byte pin;
byte positionInsideGroup;
char thePosition; // Left, Right, Up, Down
byte minAngle;
byte maxAngle;
} ledConfig;
ledConfig leds[] = {
{3, 1, 'u', 5, 15},
{12, 2, 'u', 16, 30},
{11, 3, 'u', 31, 45},
{5, 1, 'd', 5, 15},
{6, 2, 'd', 16, 30},
{7, 3, 'd', 31, 45},
{6, 1, 'r', 5, 23},
{9, 2, 'r', 24, 45},
{10, 1, 'l', 5, 23},
{4, 2, 'l', 24, 45},
};
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void setup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(9600);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
if (SIMPLE_IMPLEMENTATION) {
initializeLEDsSimple();
} else {
initializeLEDsMultiple();
}
lastPrintTime = millis();
}
void loop()
{
if (!dmpReady) return;
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
} else if (mpuIntStatus & 0x02) {
while (fifoCount < packetSize) {
fifoCount = mpu.getFIFOCount();
}
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
int x = ypr[0] * 180/M_PI;
int y = ypr[1] * 180/M_PI;
int z = ypr[2] * 180/M_PI;
Serial.print(y);Serial.print("\t");
Serial.println(z);
if (SIMPLE_IMPLEMENTATION) {
flashLEDsSimple(x, y, z);
} else {
flashLEDsMultiple(x, y, z);
}
}
}
void initializeLEDsSimple()
{
pinMode(frontLed, OUTPUT);
pinMode(bottomLed, OUTPUT);
pinMode(rightLed, OUTPUT);
pinMode(leftLed, OUTPUT);
}
void initializeLEDsMultiple()
{
for (int i=0; i<10; i++) {
pinMode(leds[i].pin, OUTPUT);
}
}
void flashLEDsSimple(int x, int y, int z)
{
if (y > 0) {
analogWrite(rightLed, y*4);
analogWrite(leftLed, 0);
} else {
analogWrite(leftLed, y*4*-1);
analogWrite(rightLed, 0);
}
if (z > 0) {
analogWrite(bottomLed, z*4);
analogWrite(frontLed, 0);
} else {
analogWrite(frontLed, z*4*-1);
analogWrite(bottomLed, 0);
}
}
void flashLEDsMultiple(int x, int y, int z)
{
for (int i=0; i<10; i++) {
Serial.print(z);Serial.print(",");Serial.print(leds[i].thePosition);Serial.print(",");Serial.println(leds[i].minAngle);
bool modified = false;
if (z < 0 && leds[i].thePosition == 'u' && abs(z) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (z > 0 && leds[i].thePosition == 'd' && abs(z) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (y < 0 && leds[i].thePosition == 'l' && abs(y) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (y > 0 && leds[i].thePosition == 'r' && abs(y) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (!modified) {
digitalWrite(leds[i].pin, LOW);
}
}
}
void dmpDataReady()
{
mpuInterrupt = true;
}
Thêm một ví dụ nửa về cảm biến 6 trục.các bạn xem video này truoc khi bắt tay vào làm nhé
Và đây là Full Code:
#include "I2Cdev.h"
#include <Adafruit_NeoPixel.h>
#include "MPU6050_6Axis_MotionApps20.h"
#include "Wire.h"
#define NEOPIXED_CONTROL_PIN 6
#define NUM_LEDS 24
const int MAX_ANGLE = 45;
const int LED_OFFSET = 12;
MPU6050 mpu;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, NEOPIXED_CONTROL_PIN, NEO_RBG + NEO_KHZ800);
unsigned long lastPrintTime = 0;
bool initialization = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
Quaternion q; // [w, x, y, z] quaternion container
VectorFloat gravity; // [x, y, z] gravity vector
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void setup()
{
Serial.begin(9600);
Serial.println("Program started");
initialization = initializeGyroscope();
strip.begin();
}
void loop()
{
if (!initialization) {
return;
}
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if (hasFifoOverflown(mpuIntStatus, fifoCount)) {
mpu.resetFIFO();
return;
}
if (mpuIntStatus & 0x02) {
while (fifoCount < packetSize) {
fifoCount = mpu.getFIFOCount();
}
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
redrawLeds(ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI);
}
}
boolean hasFifoOverflown(int mpuIntStatus, int fifoCount)
{
return mpuIntStatus & 0x10 || fifoCount == 1024;
}
void redrawLeds(int x, int y, int z)
{
x = constrain(x, -1 * MAX_ANGLE, MAX_ANGLE);
y = constrain(y, -1 * MAX_ANGLE, MAX_ANGLE);
if (y < 0 and z > 0) {
lightLeds(y, z, 0, 5, 0, 89);
} else if (y < 0 and z < 0) {
lightLeds(y, z, 6, 12, 89, 0);
} else if (y > 0 and z < 0) {
lightLeds(y, z, 13, 19, 0, 89);
} else if (y > 0 and z > 0) {
lightLeds(y, z, 20, 24, 89, 0);
}
}
void lightLeds(int x, int y, int fromLedPosition, int toLedPosition, int fromAngle, int toAngle)
{
double angle = (atan((double) abs(x) / (double) abs (y)) * 4068) / 71;
int ledNr = map(angle, fromAngle, toAngle, fromLedPosition, toLedPosition);
printDebug(x, y, ledNr, angle);
uint32_t color;
for (int i=0; i < NUM_LEDS; i++) {
color = strip.Color(0, 0, 0);
if (i == ledNr) {
color = strip.Color(0, 180, 0);
} else if (i == ledNr - 1) {
color = strip.Color(0, 5, 0);
}
strip.setPixelColor(normalizeLedPosition(i), color);
strip.show();
}
}
int normalizeLedPosition(int position)
{
if (NUM_LEDS > position + LED_OFFSET) {
return position + LED_OFFSET;
}
return position + LED_OFFSET - NUM_LEDS;
}
void printDebug(int y, int z, int lightLed, int angle)
{
if (millis() - lastPrintTime < 500) {
return;
}
Serial.print("a=");Serial.print(angle);Serial.print("; ");
Serial.print("ll=");Serial.print(lightLed);Serial.print("; ");
Serial.print("y=");Serial.print(y);Serial.print("; ");
Serial.print("z=");Serial.print(z);Serial.println("; ");
lastPrintTime = millis();
}
bool initializeGyroscope() {
Wire.begin();
TWBR = 24;
mpu.initialize();
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788);
if (devStatus != 0) {
Serial.print(F("DMP Initialization failed (code "));Serial.println(devStatus);
return false;
}
mpu.setDMPEnabled(true);
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
Serial.println(F("DMP ready! Waiting for first interrupt..."));
packetSize = mpu.dmpGetFIFOPacketSize();
return true;
}
void dmpDataReady()
{
mpuInterrupt = true;
}
Xong rồi đó
Bây giờ mình hướng dẫn làm một xe diều khiển qua bluetooth điện thoại nha
Trước tiên hãy xem video và sau đó chúng ta sẻ làm theo nhé:
Bây giờ chúng ta vào đây down file Apk về điện thoại android và cài đặt lên điện thoại trước nha để tí nửa khi mọi chuyện hoàn tất ta sẽ mở file vừa cài đặt này trên điện thoại để điều khiển chiếc xe mà ta vừa làm xong nha các bạn.
Các bạn vào đây down file Apk: DOWNLOAD
và đây là video đầy đủ của chiếc xe đúng với phần mèm mà bạn vừa cài đặt:
Bây giờ ta down code Arduino vê và nạp vào board arduino:
Đây là đoạn code Arduino:
int izqA = 5;
int izqB = 6;
int derA = 9;
int derB = 10;
int vel = 255; // Velocidad de los motores (0-255)
int estado = 'g'; // inicia detenido
void setup() {
Serial.begin(9600); // inicia el puerto serial para comunicacion con el Bluetooth
pinMode(derA, OUTPUT);
pinMode(derB, OUTPUT);
pinMode(izqA, OUTPUT);
pinMode(izqB, OUTPUT);
}
void loop() {
if(Serial.available()>0){ // lee el bluetooth y almacena en estado
estado = Serial.read();
}
if(estado=='a'){ // Forward
Serial.println(estado);
analogWrite(derB, 0);
analogWrite(izqB, 0);
analogWrite(derA, vel);
analogWrite(izqA, vel);
}
if(estado=='d'){ // right
Serial.println(estado);
analogWrite(derB, vel);
analogWrite(izqB, 0);
analogWrite(derA, 0);
analogWrite(izqA, vel);
}
if(estado=='c'){ // Stop
Serial.println(estado);
analogWrite(derB, 0);
analogWrite(izqB, 0);
analogWrite(derA, 0);
analogWrite(izqA, 0);
}
if(estado=='b'){ // left
Serial.println(estado);
analogWrite(derB, 0);
analogWrite(izqB, vel);
analogWrite(izqA, 0);
analogWrite(derA, vel);
}
if(estado=='e'){ // Reverse
Serial.println(estado);
analogWrite(derA, 0);
analogWrite(izqA, 0);
analogWrite(derB, vel);
analogWrite(izqB, vel);
}
if (estado =='f'){ // Boton ON se mueve sensando distancia
}
if (estado=='g'){ // Boton OFF, detiene los motores no hace nada
}
}
bắt đầu nhé:
Đầu tiên down phần mềm này về cài đặt lên điện thoại Android: DOWNLOAD
Tiếp đến down file này về: DOWNLOAD
và giải nén ra trong đó gồm có mấy bộ thư viện dành cho arduino và một file code Arduino .các bạn Add các file thư viện này vào phần mềm lập trình Arduino trên máy tính xong rối mở file : denge_robot.ino mà ta vừa giải nén ra đó copy và dán file này vào trình soạn thảo Arduino rồi nạp vào board Arduino nhé
Vào đây để down thư viện của nó: DOWNLOAD và thư viện I2C: DOWNLOAD
Add 2 thư viện trên vào trình soạn thảo Arduino rồi xem video này trước khi bắt tay vào làm
Bây giờ ta down code nay về và dán vào trình soạn thảo Arduino tiếp đến nạp vào board Arduino rồi lắp mạch như trong Video rồi cấp nguồn cho chạy thử
Vào đây down code arduino: DOWNLOAD
hoặc có thể chép trực tiếp ở đây rồi dán vào trình soạn thảo Arduino:
Đoạn code của nó là:
/**
* Simple implementation false
* means that for pitch/yaw there only be
* a single led for each direction. The led will get more bright
* as the direction increases
* Simple implementation true
* means that for pitch/yaw there will be multiple led's that light up one by one
* The accelerometer/gyro is a MPU6050, it should be wired to the SDA and SCL pins
*/
#define SIMPLE_IMPLEMENTATION false
const int frontLed = 3;
const int bottomLed = 5;
const int rightLed = 6;
const int leftLed = 9;
long int lastPrintTime;
typedef struct
{
byte pin;
byte positionInsideGroup;
char thePosition; // Left, Right, Up, Down
byte minAngle;
byte maxAngle;
} ledConfig;
ledConfig leds[] = {
{3, 1, 'u', 31, 45},
{12, 2, 'u', 16, 30},
{11, 3, 'u', 5, 15},
{5, 1, 'd', 5, 15},
{6, 2, 'd', 16, 30},
{7, 3, 'd', 31, 45},
{8 , 1, 'r', 5, 23},
{9, 2, 'r', 24, 45},
{10, 1, 'l', 5, 23},
{4, 2, 'l', 24, 45},
};
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void setup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(9600);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
if (SIMPLE_IMPLEMENTATION) {
initializeLEDsSimple();
} else {
initializeLEDsMultiple();
}
lastPrintTime = millis();
}
void loop()
{
if (!dmpReady) return;
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
} else if (mpuIntStatus & 0x02) {
while (fifoCount < packetSize) {
fifoCount = mpu.getFIFOCount();
}
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
int x = ypr[0] * 180/M_PI;
int y = ypr[1] * 180/M_PI;
int z = ypr[2] * 180/M_PI;
Serial.print(y);Serial.print("\t");Serial.println(z);
if (SIMPLE_IMPLEMENTATION) {
flashLEDsSimple(x, y, z);
} else {
flashLEDsMultiple(x, y, z);
}
}
}
void initializeLEDsSimple()
{
pinMode(frontLed, OUTPUT);
pinMode(bottomLed, OUTPUT);
pinMode(rightLed, OUTPUT);
pinMode(leftLed, OUTPUT);
}
void initializeLEDsMultiple()
{
for (int i=0; i<10; i++) {
Serial.println(leds[i].pin);
pinMode(leds[i].pin, OUTPUT);
}
delay(3000);
}
void flashLEDsSimple(int x, int y, int z)
{
if (y > 0) {
analogWrite(rightLed, y*4);
analogWrite(leftLed, 0);
} else {
analogWrite(leftLed, y*4*-1);
analogWrite(rightLed, 0);
}
if (z > 0) {
analogWrite(bottomLed, z*4);
analogWrite(frontLed, 0);
} else {
analogWrite(frontLed, z*4*-1);
analogWrite(bottomLed, 0);
}
}
void flashLEDsMultiple(int x, int y, int z)
{
for (int i=0; i<10; i++) {
//Serial.print(z);Serial.print(",");Serial.print(leds[i].thePosition);Serial.print(",");Serial.println(leds[i].minAngle);
bool modified = false;
if (z < 0 && leds[i].thePosition == 'u' && abs(z) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (z > 0 && leds[i].thePosition == 'd' && abs(z) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (y < 0 && leds[i].thePosition == 'l' && abs(y) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (y > 0 && leds[i].thePosition == 'r' && abs(y) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (!modified) {
digitalWrite(leds[i].pin, LOW);
}
}
}
void dmpDataReady()
{
mpuInterrupt = true;
}
Vậy là ta đã hoàn thành một ví dụ rồi đó.
ta xem tiếp tục một ví dụ về cảm biến 6 trục nửa nha
Và đây là video cách vận hành của nó:
Và đây là Full code của nó:
/**
* Simple implementation false
* means that for pitch/yaw there only be
* a single led for each direction. The led will get more bright
* as the direction increases
*
* Simple implementation true
* means that for pitch/yaw there will be multiple led's that light up one by one
* The accelerometer is a MPU6050, it should be wired to the SDA and SCL pins
*/
#define SIMPLE_IMPLEMENTATION true
const int frontLed = 3;
const int bottomLed = 5;
const int rightLed = 6;
const int leftLed = 9;
long int lastPrintTime;
typedef struct
{
byte pin;
byte positionInsideGroup;
char thePosition; // Left, Right, Up, Down
byte minAngle;
byte maxAngle;
} ledConfig;
ledConfig leds[] = {
{3, 1, 'u', 5, 15},
{12, 2, 'u', 16, 30},
{11, 3, 'u', 31, 45},
{5, 1, 'd', 5, 15},
{6, 2, 'd', 16, 30},
{7, 3, 'd', 31, 45},
{6, 1, 'r', 5, 23},
{9, 2, 'r', 24, 45},
{10, 1, 'l', 5, 23},
{4, 2, 'l', 24, 45},
};
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 mpu;
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void setup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(9600);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
if (SIMPLE_IMPLEMENTATION) {
initializeLEDsSimple();
} else {
initializeLEDsMultiple();
}
lastPrintTime = millis();
}
void loop()
{
if (!dmpReady) return;
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
} else if (mpuIntStatus & 0x02) {
while (fifoCount < packetSize) {
fifoCount = mpu.getFIFOCount();
}
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
int x = ypr[0] * 180/M_PI;
int y = ypr[1] * 180/M_PI;
int z = ypr[2] * 180/M_PI;
Serial.print(y);Serial.print("\t");
Serial.println(z);
if (SIMPLE_IMPLEMENTATION) {
flashLEDsSimple(x, y, z);
} else {
flashLEDsMultiple(x, y, z);
}
}
}
void initializeLEDsSimple()
{
pinMode(frontLed, OUTPUT);
pinMode(bottomLed, OUTPUT);
pinMode(rightLed, OUTPUT);
pinMode(leftLed, OUTPUT);
}
void initializeLEDsMultiple()
{
for (int i=0; i<10; i++) {
pinMode(leds[i].pin, OUTPUT);
}
}
void flashLEDsSimple(int x, int y, int z)
{
if (y > 0) {
analogWrite(rightLed, y*4);
analogWrite(leftLed, 0);
} else {
analogWrite(leftLed, y*4*-1);
analogWrite(rightLed, 0);
}
if (z > 0) {
analogWrite(bottomLed, z*4);
analogWrite(frontLed, 0);
} else {
analogWrite(frontLed, z*4*-1);
analogWrite(bottomLed, 0);
}
}
void flashLEDsMultiple(int x, int y, int z)
{
for (int i=0; i<10; i++) {
Serial.print(z);Serial.print(",");Serial.print(leds[i].thePosition);Serial.print(",");Serial.println(leds[i].minAngle);
bool modified = false;
if (z < 0 && leds[i].thePosition == 'u' && abs(z) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (z > 0 && leds[i].thePosition == 'd' && abs(z) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (y < 0 && leds[i].thePosition == 'l' && abs(y) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (y > 0 && leds[i].thePosition == 'r' && abs(y) > leds[i].minAngle) {
digitalWrite(leds[i].pin, HIGH);
modified = true;
}
if (!modified) {
digitalWrite(leds[i].pin, LOW);
}
}
}
void dmpDataReady()
{
mpuInterrupt = true;
}
Thêm một ví dụ nửa về cảm biến 6 trục.các bạn xem video này truoc khi bắt tay vào làm nhé
Và đây là Full Code:
#include "I2Cdev.h"
#include <Adafruit_NeoPixel.h>
#include "MPU6050_6Axis_MotionApps20.h"
#include "Wire.h"
#define NEOPIXED_CONTROL_PIN 6
#define NUM_LEDS 24
const int MAX_ANGLE = 45;
const int LED_OFFSET = 12;
MPU6050 mpu;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, NEOPIXED_CONTROL_PIN, NEO_RBG + NEO_KHZ800);
unsigned long lastPrintTime = 0;
bool initialization = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
Quaternion q; // [w, x, y, z] quaternion container
VectorFloat gravity; // [x, y, z] gravity vector
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void setup()
{
Serial.begin(9600);
Serial.println("Program started");
initialization = initializeGyroscope();
strip.begin();
}
void loop()
{
if (!initialization) {
return;
}
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if (hasFifoOverflown(mpuIntStatus, fifoCount)) {
mpu.resetFIFO();
return;
}
if (mpuIntStatus & 0x02) {
while (fifoCount < packetSize) {
fifoCount = mpu.getFIFOCount();
}
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
redrawLeds(ypr[0] * 180/M_PI, ypr[1] * 180/M_PI, ypr[2] * 180/M_PI);
}
}
boolean hasFifoOverflown(int mpuIntStatus, int fifoCount)
{
return mpuIntStatus & 0x10 || fifoCount == 1024;
}
void redrawLeds(int x, int y, int z)
{
x = constrain(x, -1 * MAX_ANGLE, MAX_ANGLE);
y = constrain(y, -1 * MAX_ANGLE, MAX_ANGLE);
if (y < 0 and z > 0) {
lightLeds(y, z, 0, 5, 0, 89);
} else if (y < 0 and z < 0) {
lightLeds(y, z, 6, 12, 89, 0);
} else if (y > 0 and z < 0) {
lightLeds(y, z, 13, 19, 0, 89);
} else if (y > 0 and z > 0) {
lightLeds(y, z, 20, 24, 89, 0);
}
}
void lightLeds(int x, int y, int fromLedPosition, int toLedPosition, int fromAngle, int toAngle)
{
double angle = (atan((double) abs(x) / (double) abs (y)) * 4068) / 71;
int ledNr = map(angle, fromAngle, toAngle, fromLedPosition, toLedPosition);
printDebug(x, y, ledNr, angle);
uint32_t color;
for (int i=0; i < NUM_LEDS; i++) {
color = strip.Color(0, 0, 0);
if (i == ledNr) {
color = strip.Color(0, 180, 0);
} else if (i == ledNr - 1) {
color = strip.Color(0, 5, 0);
}
strip.setPixelColor(normalizeLedPosition(i), color);
strip.show();
}
}
int normalizeLedPosition(int position)
{
if (NUM_LEDS > position + LED_OFFSET) {
return position + LED_OFFSET;
}
return position + LED_OFFSET - NUM_LEDS;
}
void printDebug(int y, int z, int lightLed, int angle)
{
if (millis() - lastPrintTime < 500) {
return;
}
Serial.print("a=");Serial.print(angle);Serial.print("; ");
Serial.print("ll=");Serial.print(lightLed);Serial.print("; ");
Serial.print("y=");Serial.print(y);Serial.print("; ");
Serial.print("z=");Serial.print(z);Serial.println("; ");
lastPrintTime = millis();
}
bool initializeGyroscope() {
Wire.begin();
TWBR = 24;
mpu.initialize();
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788);
if (devStatus != 0) {
Serial.print(F("DMP Initialization failed (code "));Serial.println(devStatus);
return false;
}
mpu.setDMPEnabled(true);
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
Serial.println(F("DMP ready! Waiting for first interrupt..."));
packetSize = mpu.dmpGetFIFOPacketSize();
return true;
}
void dmpDataReady()
{
mpuInterrupt = true;
}
Xong rồi đó
Bây giờ mình hướng dẫn làm một xe diều khiển qua bluetooth điện thoại nha
Trước tiên hãy xem video và sau đó chúng ta sẻ làm theo nhé:
Bây giờ chúng ta vào đây down file Apk về điện thoại android và cài đặt lên điện thoại trước nha để tí nửa khi mọi chuyện hoàn tất ta sẽ mở file vừa cài đặt này trên điện thoại để điều khiển chiếc xe mà ta vừa làm xong nha các bạn.
Các bạn vào đây down file Apk: DOWNLOAD
và đây là video đầy đủ của chiếc xe đúng với phần mèm mà bạn vừa cài đặt:
Bây giờ ta down code Arduino vê và nạp vào board arduino:
Đây là đoạn code Arduino:
int izqA = 5;
int izqB = 6;
int derA = 9;
int derB = 10;
int vel = 255; // Velocidad de los motores (0-255)
int estado = 'g'; // inicia detenido
void setup() {
Serial.begin(9600); // inicia el puerto serial para comunicacion con el Bluetooth
pinMode(derA, OUTPUT);
pinMode(derB, OUTPUT);
pinMode(izqA, OUTPUT);
pinMode(izqB, OUTPUT);
}
void loop() {
if(Serial.available()>0){ // lee el bluetooth y almacena en estado
estado = Serial.read();
}
if(estado=='a'){ // Forward
Serial.println(estado);
analogWrite(derB, 0);
analogWrite(izqB, 0);
analogWrite(derA, vel);
analogWrite(izqA, vel);
}
if(estado=='d'){ // right
Serial.println(estado);
analogWrite(derB, vel);
analogWrite(izqB, 0);
analogWrite(derA, 0);
analogWrite(izqA, vel);
}
if(estado=='c'){ // Stop
Serial.println(estado);
analogWrite(derB, 0);
analogWrite(izqB, 0);
analogWrite(derA, 0);
analogWrite(izqA, 0);
}
if(estado=='b'){ // left
Serial.println(estado);
analogWrite(derB, 0);
analogWrite(izqB, vel);
analogWrite(izqA, 0);
analogWrite(derA, vel);
}
if(estado=='e'){ // Reverse
Serial.println(estado);
analogWrite(derA, 0);
analogWrite(izqA, 0);
analogWrite(derB, vel);
analogWrite(izqB, vel);
}
if (estado =='f'){ // Boton ON se mueve sensando distancia
}
if (estado=='g'){ // Boton OFF, detiene los motores no hace nada
}
}
Hoặc có thể down ở đây: DOWNLOAD
Hướng dẫn kết nối dây:
Motors Connection:
Out1 -> Left Side Motor Red Wire (+ )
Out2 -> Left Side Motor Black Wire ( - )
Out3 -> Right Side Motor Red Wire ( + )
Out4 -> Right Side Motor Black Wire ( - )
LM298 - > Arduino
IN1 -> D5
IN2-> D6
IN2 ->D9
IN2-> D10
Bluetooth Module -> Arduino
Rx-> Tx
Tx ->Rx
GND -> GND
Vcc -> 3.3V
Power
12V - > Connect Battery Red Wire
GND -> Connect Battery Black wire and Arduino GND pin
5V -> Connect to Arduino 5V pin
Hướng dẫn mạch cầu H:
H bridges are available as integrated circuits, or you can built your own by using 4transistors or MOSFETs.
In our case we are using LM298 H-bridge IC that can allows to control the speed and direction of the motors.
Pin Description :
Out 1: DC motor 1 "+" or stepper motor A+
Out 2: DC motor 1 "-" or stepper motor A-
Out 3: DC motor 2 "+" or stepper motor B+
Out 4: Motor B lead out
12v :12V input but you can use 7 to 35V
GND: Ground
5v: 5V output if 12V jumper in place, ideal for powering your Arduino (etc)
EnA: Enables PWM signal for Motor A (Please see the "Arduino Sketch Considerations" section)
IN1: Enable Motor A
IN2: Enable MotorA
IN3: Enable MotorB
IN4: Enable MotorB
BEnB: Enables PWM signal for Motor B (Please see the "Arduino Sketch Considerations" section)
Vậy là xong rồi đó.(chú ý ở đây xe chỉ có chức năng điều khiển qua điên thoại chứ không có gắn module tránh vật cản bằng siêu âm và động cơ servo trên đó nha các bạn)
Nếu muốn làm chiếc xe tự chạy có thể tránh vật cản trên đường thì các bạn tham khảo thêm đoạn code dưới đây:
// Arduino Obstacle Avoiding Robot
// Code adapted from http://www.educ8s.tv
// First Include the NewPing and Servo Libraries
#include <NewPing.h>
#include <Servo.h>
#define TRIG_PIN A4
#define ECHO_PIN A5
#define MAX_DISTANCE 200
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);
Servo myservo;
boolean goesForward=false;
int distance = 100;
int speedSet = 0;
const int motorPin1 = 11;
const int motorPin2 = 10;
//Motor B
const int motorPin3 = 6;
const int motorPin4 = 5;
void setup() {
myservo.attach(9);
myservo.write(115);
delay(2000);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
}
void loop() {
int distanceR = 0;
int distanceL = 0;
delay(40);
if(distance<=20)
{
moveStop();
delay(100);
moveBackward();
delay(300);
moveStop();
delay(200);
distanceR = lookRight();
delay(200);
distanceL = lookLeft();
delay(200);
if(distanceR>=distanceL)
{
turnRight();
moveStop();
}else
{
turnLeft();
moveStop();
}
}else
{
moveForward();
}
distance = readPing();
}
int lookRight()
{
myservo.write(50);
delay(500);
int distance = readPing();
delay(100);
myservo.write(115);
return distance;
}
int lookLeft()
{
myservo.write(170);
delay(500);
int distance = readPing();
delay(100);
myservo.write(115);
return distance;
delay(100);
}
int readPing() {
delay(70);
int cm = sonar.ping_cm();
if(cm==0)
{
cm = 250;
}
return cm;
}
void moveStop() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, 0);
}
void moveForward() {
analogWrite(motorPin1, 180);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 180);
analogWrite(motorPin4, 0);
}
void moveBackward() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, 180);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, 180);
}
void turnRight() {
analogWrite(motorPin1, 180);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, 180);
delay(300);
moveForward();
}
void turnLeft() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, 180);
analogWrite(motorPin3, 180);
analogWrite(motorPin4, 0);
delay(300);
moveForward();
}
Bài này mình sẽ nói về chủ đề Arduino và xe 2 bánh tự giữ thăng bằng
Hướng dẫn kết nối dây:
Motors Connection:
Out1 -> Left Side Motor Red Wire (+ )
Out2 -> Left Side Motor Black Wire ( - )
Out3 -> Right Side Motor Red Wire ( + )
Out4 -> Right Side Motor Black Wire ( - )
LM298 - > Arduino
IN1 -> D5
IN2-> D6
IN2 ->D9
IN2-> D10
Bluetooth Module -> Arduino
Rx-> Tx
Tx ->Rx
GND -> GND
Vcc -> 3.3V
Power
12V - > Connect Battery Red Wire
GND -> Connect Battery Black wire and Arduino GND pin
5V -> Connect to Arduino 5V pin
Hướng dẫn mạch cầu H:
H bridges are available as integrated circuits, or you can built your own by using 4transistors or MOSFETs.
In our case we are using LM298 H-bridge IC that can allows to control the speed and direction of the motors.
Pin Description :
Out 1: DC motor 1 "+" or stepper motor A+
Out 2: DC motor 1 "-" or stepper motor A-
Out 3: DC motor 2 "+" or stepper motor B+
Out 4: Motor B lead out
12v :12V input but you can use 7 to 35V
GND: Ground
5v: 5V output if 12V jumper in place, ideal for powering your Arduino (etc)
EnA: Enables PWM signal for Motor A (Please see the "Arduino Sketch Considerations" section)
IN1: Enable Motor A
IN2: Enable MotorA
IN3: Enable MotorB
IN4: Enable MotorB
BEnB: Enables PWM signal for Motor B (Please see the "Arduino Sketch Considerations" section)
Vậy là xong rồi đó.(chú ý ở đây xe chỉ có chức năng điều khiển qua điên thoại chứ không có gắn module tránh vật cản bằng siêu âm và động cơ servo trên đó nha các bạn)
Nếu muốn làm chiếc xe tự chạy có thể tránh vật cản trên đường thì các bạn tham khảo thêm đoạn code dưới đây:
// Arduino Obstacle Avoiding Robot
// Code adapted from http://www.educ8s.tv
// First Include the NewPing and Servo Libraries
#include <NewPing.h>
#include <Servo.h>
#define TRIG_PIN A4
#define ECHO_PIN A5
#define MAX_DISTANCE 200
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);
Servo myservo;
boolean goesForward=false;
int distance = 100;
int speedSet = 0;
const int motorPin1 = 11;
const int motorPin2 = 10;
//Motor B
const int motorPin3 = 6;
const int motorPin4 = 5;
void setup() {
myservo.attach(9);
myservo.write(115);
delay(2000);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
}
void loop() {
int distanceR = 0;
int distanceL = 0;
delay(40);
if(distance<=20)
{
moveStop();
delay(100);
moveBackward();
delay(300);
moveStop();
delay(200);
distanceR = lookRight();
delay(200);
distanceL = lookLeft();
delay(200);
if(distanceR>=distanceL)
{
turnRight();
moveStop();
}else
{
turnLeft();
moveStop();
}
}else
{
moveForward();
}
distance = readPing();
}
int lookRight()
{
myservo.write(50);
delay(500);
int distance = readPing();
delay(100);
myservo.write(115);
return distance;
}
int lookLeft()
{
myservo.write(170);
delay(500);
int distance = readPing();
delay(100);
myservo.write(115);
return distance;
delay(100);
}
int readPing() {
delay(70);
int cm = sonar.ping_cm();
if(cm==0)
{
cm = 250;
}
return cm;
}
void moveStop() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, 0);
}
void moveForward() {
analogWrite(motorPin1, 180);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 180);
analogWrite(motorPin4, 0);
}
void moveBackward() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, 180);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, 180);
}
void turnRight() {
analogWrite(motorPin1, 180);
analogWrite(motorPin2, 0);
analogWrite(motorPin3, 0);
analogWrite(motorPin4, 180);
delay(300);
moveForward();
}
void turnLeft() {
analogWrite(motorPin1, 0);
analogWrite(motorPin2, 180);
analogWrite(motorPin3, 180);
analogWrite(motorPin4, 0);
delay(300);
moveForward();
}
Bài này mình sẽ nói về chủ đề Arduino và xe 2 bánh tự giữ thăng bằng
bắt đầu nhé:
Đầu tiên down phần mềm này về cài đặt lên điện thoại Android: DOWNLOAD
Tiếp đến down file này về: DOWNLOAD
và giải nén ra trong đó gồm có mấy bộ thư viện dành cho arduino và một file code Arduino .các bạn Add các file thư viện này vào phần mềm lập trình Arduino trên máy tính xong rối mở file : denge_robot.ino mà ta vừa giải nén ra đó copy và dán file này vào trình soạn thảo Arduino rồi nạp vào board Arduino nhé
Đăng ký:
Nhận xét (Atom)



































