آردوینو اپلیکیشن برد ESP8266 برد ویموس Wemos

آموزش ساخت اپلیکیشن اختصاصی اندروید برای بردهای آردوینو Arduino

create-android-app-for-arduino-digispark
نوشته شده توسط نیلوفر مهرنیا

حتما تا به‌حال اپلیکیشن‌های آماده‌ای را دیده‌اید که با بردهای خاصی در پروتکل خاصی ارتباط برقرار می‌کنند. اما این اپلیکیشن‌ها کاربردی عمومی دارند و برای ما شخصی‌سازی ‌شده نیستند. پس طبیعی است که نیازهای ما را کامل برطرف نسازند و رضایت کامل ما را جلب نکنند. در اینجاست که باید خودمان دست به کار شویم و اپلیکیشن مورد نیاز خود را با ظاهر و عملکرد اختصاصی بسازیم. در این آموزش قصد داریم اپلیکیشن اندرویدی برای ارتباط با ESP8266 یا تمام بردهای دارای این تراشه بنویسیم و نحوه ارسال و دریافت اطلاعات را بیاموزیم. در این آموزش برای ارتباط بین اندروید و برد ESP8266 از پروتکل وای فای و ساختار داده JSON استفاده می‌کنیم. برای برنامه‌نویسی اپلیکیشن از زبان جاوا و از محیط اندروید استودیو بهره می‌بریم. برای برنامه‌نویسی برد از Arduino IDE استفاده می‌کنیم. می‌خواهیم اپلیکیشنی طراحی کنیم که دما را از برد گرفته و نمایش دهد. در ادامه این آموزش با مرجع تخصصی آردوینو به زبان فارسی، دیجی اسپارک همراه باشید.

 


برنامه‌نویسی آردوینو


ارتباط برد آردوینو با اپلیکیشن از طریق Json صورت می‌گیرد. برای استفاده از JSON در Arduino IDE پیش از هر کاری، آموزش استفاده از JSON در آردوینو Arduino IDE را مطالعه کنید. باید وای فای برد را به‌صورت اکسس پوینت تعریف کنیم تا تلفن همراه به‌صورت کلاینت به آن وای فای متصل شود. تعریف اکسس پوینت و کلاینت را در آموزش ساخت اکسس پوینت و کلاینت در Esp8266 بخوانید.

#include <ESP8266WiFi.h>   //library for ESP8266
#include <ESP8266WebServer.h>   //library for server
#include <ArduinoJson.h>   //library for json
#include <DallasTemperature.h>   //libraries for temprature
#include <Wire.h>
#define ONE_WIRE_BUS D3  //pin of sensor

IPAddress local_IP(192,168,11,4);   // Server IP
IPAddress subnet(255,255,255,0);

ESP8266WebServer server;
DynamicJsonDocument doc(1024);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);

void tempActivity(){
   String Webpage;
   DS18B20.requestTemperatures();
   int temp = DS18B20.getTempCByIndex(0);   // خواندن دما از سنسور
   doc["tempnow"] =temp;
   serializeJson(doc,Webpage);   // ساختار json وارد متغیر webpage می‌شود
   server.send(200, "text/plain",Webpage + "\n" );   // ارسال دیتا به کلاینت‌ها
}

void setup() {
  Serial.begin(115200);
  // تنظیمات وای فای
  WiFi.softAPConfig(local_IP,local_IP,subnet);
  Serial.print("Setting soft_AP ...");
  WiFi.softAP("wemos_d1", "1234567890");
  WiFi.softAPIP();
  WiFi.mode(WIFI_AP);   // تعریف به‌صورت اکسس پوینت

server.begin();
  server.on("/temp", tempActivity);   // وقتی دستور temp برسد تابع tempActivity فراخوانی می‌شود
}

void loop() {
   server.handleClient();   // آماده  بودن برای درخواست کلاینت‌ها
}

 

در کد فوق وقتی دستور گرفتن دما از سوی اپلیکیشن بیاید، تابع tempActivity فراخوانی می‌شود و در آن تابع مقدار دمای خوانده‌شده‌ی زمان حال برای اپلیکیشن فرستاده می‌شود. وقتی مقدار دما در متغیر Webpage سریالایز می‌شود، ساختار جیسون در این متغیر برای مثال به‌صورت String زیر است.

{"tempnow": 25}

 

 


اتصالات مدار


در این پست از سنسور دما DS18B20 استفاده کرده‌ایم. اتصالات سه پایه این سنسور را مطالبق توضیحات ادامه انجام دهید. پایه Vcc سنسور را به پایه ۵ ولت برد، پایه GND سنسور را به GND برد و پایه Data سنسور را به D3 متصل کنید.

 


برنامه‌نویسی اپلیکیشن اندروید


برای استفاده از JSON در اندروید استودیو با استفاده از کتابخانه retrofit لازم است خطوط زیر را به آن اضافه کنید. اگر طرز اضافه کردن کتابخانه را نمی‌دانید به آموزش افزودن کتابخانه در نرم‌افزار اندروید استودیو Android Studio مراجعه کنید.

implementation 'com.squareup.retrofit2:retrofit:2.6.2'
implementation 'com.squareup.retrofit2:converter-gson:2.6.2'

و دسترسی زیر را به مانیفست اپلیکیشن اضافه می‌کنیم:

    <uses-permission android:name="android.permission.INTERNET" />

سپس یک کلاس به نام ServiceGenerator می‌سازیم و کدهای زیر را درونش می‌نویسیم:

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ServiceGenerator {
// ای پی معرفی‌شده سرور در قسمت آردوینو
    public static final String API_BASE_URL = "http://192.168.11.4/";
    private static OkHttpClient httpClient = new OkHttpClient.Builder().build();
    private static Retrofit.Builder builder = new Retrofit.Builder().baseUrl(API_BASE_URL).addConverterFactory(GsonConverterFactory.create());
    public static <S> S createService(Class<S> serviceClass) }
Retrofit retrofit = builder.client(httpClient).build();
        return retrofit.create(serviceClass);
    }
}

 

برای استفاده از JSON اول باید یک مدل از روی آن بسازیم. اگر ساختن مدل برایتان سخت است، می‌توانید از ابزارهای آماده برای ساخت مدل  JSON استفاده کنید. یکی از این ابزارها سایت www.jsonschema2pojo.org است که با نوشتن داده‌های خود به‌صورت JSON می‌توانید توابع موردنیاز را به‌صورت آماده دریافت کنید. دقت کنید گزینه‌های تیک خورده مانند عکس زیر باشد.

سپس می‌توانید از گزینه Preview یا Zip کدها را دریافت کنید. این کدها را در یک کلاس جاوا در برنامه ذخیره کنید. (برای مثال نام کلاس Category در نظر گرفته‌شده است.)

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Category {
@SerializedName("tempnow")
@Expose
private Integer tempnow;
public Integer getTempnow() {
return tempnow;
}
public void setTempnow(Integer tempnow) {
this.tempnow = tempnow;
}
}

 


دریافت از آردوینو با دستور GET


در قدم بعدی لازم است یک اینترفیس به نام StoreClient بسازید و به‌صورت زیر آن را کامل کنید.

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;

public interface StoreClient {

    @GET("temp")
    Call<Category> getData();
{

توجه کنید که آدرس نوشته‌شده در جلوی GET باید با دستوری که در آردوینو برای فراخوانی تابع معرفی کردیم یکسان باشد. حالا نوبت به UI اپلیکیشن می‌رسد که ما یک دکمه به شکل زیر تعریف می‌کنیم تا با فشردن آن دما نمایش داده شود.

  <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">
    <TextView
        android:id="@+id/txt_temp_activity"
        android:layout_width="160dp"
        android:layout_height="40dp"
        android:layout_gravity="center"
        />
    <Button
        android:id="@+id/btn_temp_activity"
        android:layout_width="160dp"
        android:layout_height="40dp"
        android:layout_gravity="center"
        android:text="دما"
        android:textSize="13dp"></Button>

</LinearLayout>

 

 


کدهای جاوای اکتیویتی


 

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
    Button btn_temp_activity;
    TextView tv_temp;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_temp_activity = findViewById(R.id.btn_temp_activity);
        tv_temp = findViewById(R.id.txt_temp_activity);
        btn_temp_activity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                StoreClient storeClient = ServiceGenerator.createService(StoreClient.class);
                Call<Category> call = storeClient.getData();
                call.enqueue(new Callback<Category>() {
                    @Override
                    public void onResponse(Call<Category> call, Response<Category> response) {
                        if (response.isSuccessful()) {
                            Category category = response.body();
                            tv_temp.setText(category.getTempnow() + "");
                        }
                    }
                    @Override
                    public void onFailure(Call<Category> call, Throwable t) {
                    }
                });
            }
        });
    }
}

به همین سادگی توانستیم داده‌ها را در گوشی خود دریافت کنیم.

 


ارسال به آردوینو با دستور POST


برای ارسال اطلاعات از گوشی به آردوینو هم باید از دستور POST استفاده کنیم. برای مثال یک متن را به آردوینو می‌فرستیم. لازم است تابع مربوطه را در آردوینو بنویسید.

void Hi(){
    doc["HI"] = server.arg("HI");
    serializeJson(doc["HI"], Serial);
}

و در setup آن را معرفی کنید:

  server.on("/Hi", Hi);

در بخش اندروید در اینترفیس StoreClient این کدها را اضافه می‌کنیم:

@POST("Hi")
    @FormUrlEncoded
    Call<Category> sendtoArduino(@Field("HI") String hi);

حواستان باشد نام فیلدهای JSON در اندروید و آردوینو متفاوت تعریف نشود.

در کلاس مدل Category، این‌ها را اضافه می‌کنیم:

@SerializedName("HI")
@Expose
private String hI;

public String getHI() {
return hI;
}

public void setHI(String hI) {
this.hI = hI;
}

دکمه دیگری تعریف می‌کنیم تا با فشردن آن، پیام تعریف‌شده در سریال مانیتور آردوینو نمایش داده شود:

<Button
        android:id="@+id/btn_hi"
        android:layout_width="160dp"
        android:layout_height="40dp"
        android:layout_gravity="center"
        android:text="سلام"
        android:textSize="13dp"></Button>

و در کدهای جاوای آن می‌نویسیم:

Button btn_hi;
String hi = "hello Arduino!";
btn_hi = findViewById(R.id.btn_hi);
        btn_hi.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                StoreClient storeClient = ServiceGenerator.createService(StoreClient.class);
                Call<Category> call = storeClient.sendtoArduino(hi);
                call.enqueue(new Callback<Category>() {
                    @Override
                    public void onResponse(Call<Category> call, Response<Category> response) {
                    }

                    @Override
                    public void onFailure(Call<Category> call, Throwable t) {
                    }
                });
            }
        });

با کامپایل کردن کد روی آردوینو و اجرا کردن اپلیکیشن روی اندروید خواهید دید با زدن یکی از دکمه‌ها، پیغامی روی سریال مانیتور چاپ می‌شود و با فشردن دکمه دیگر دما از سنسور خوانده‌شده و در اپلیکیشن نمایش داده می‌شود. شما پس‌ازاین می‌توانید هر داده دیگری را از این طریق منتقل کنید و اپلیکیشن های دلخواه خود را برای کنترل برد آردوینو داشته باشید.

 


وسایل مورد نیاز


برد wemos d1 mini یا برد node mcu یا هر برد دیگری با ESP8266

سنسور دمای DS18B20

تلفن همراه دارای اندروید ۴ به بالا

 

چنانچه در مراحل راه اندازی و انجام این پروژه با مشکل مواجه شدید، بدون هیچ نگرانی در انتهای همین پست، به صورت ثبت نظر سوالتان را مطرح کنید. من در سریع‌ترین زمان ممکن پاسخ رفع مشکل شما را خواهم داد. همچنین اگر ایرادی در کدها و یا مراحل اجرایی وجود دارند می‌توانید از همین طریق اطلاع رسانی کنید.

 

 


پروژه و دریافت بن ارسال رایگان


برای دریافت بن خرید از دانشجو کیت، کاربران بایستی با استفاده از وسایل این آموزش، پروژه را اجرا کرده و یا حتی مدار جدیدی تعریف کنید. سپس از اجرای کار فیلم گرفته و در شبکه‌های اجتماعی از جمله آپارات و اینستگرام، با هشتگ‌های دیجی_اسپارک دانشجوکیت digispark daneshjookit منتشر کنند. سپس از طریق بخش نظرات در ادامه همین آموزش، جهت دریافت بن خرید ارسال رایگان به ارزش ۱۲۰۰۰ تومان از دانشجو کیت، لینک را زیر همین پست ارسال کنید.

 

درباره نویسنده

نیلوفر مهرنیا

مهندس نرم افزار

تبادل نظر و رفع عیب با ثبت دیدگاه

۲۱ دیدگاه

  • سلام
    من تا به حال اندروید کار نکردم اما پروژه های زیادی با آردوینو انجام دادم. آیا با آموزش های شما میتونم اپلیکشن خیلی ساده فقط برای کنترل خروجی ها مثلا رله طراحی کنم؟

  • سلام، به من در کلاس servisegenerator در خط ۱۵ خطا میده، عکسش رو در لینک زیر قرار دادم
    *************.png

  • سلام خسته نباشید من یک مداری رو با esp8266 طراحی کردم و یک اپلیکیشن هم با بیسیک فور اندروید طراحی کردم خواستم ببینم میتونم یه کاری کنم که از طریق اینترنت و از راه دور با اپلیکیشن بتونم ماژول رو کنترل کنم؟ هر منبعی رو تو اینترنت میگردم چیزی که میخوام رو پیدا نمیکنم ممنون میشم کمکم کنید

  • سلام واقعا عالی بود. چطور می تونیم به جای اینکه آردوینو منتظر temp از اندروید بمونه برای ارسال دیتا به اندروید، به طور پیوسته دما رو برای ما روی اپلیکیشن نشون بده؟ ممنون از زحماتتون.

  • سلام خدمت شما من این آپ و راه اندازی کردم ولی گوشیم اندروید ۱۱ و هیچ عکس العملی نشون نمیده
    ولی نسخه های پایین تر مثل ۴٫۴ که گوشی قدیمیمه جواب میده میشه راهنمایی کنین واسه نسخه بالاتر چیکار باید بکنم ؟

    • سلام نسخه ۴ اندروید خیلی قدیمی است. احتمال مشکل وجود دارد اما تست نشده است.

  • سلام
    ضمن تشکر از آموزشهای خوب شما لطفاً ساخت و ارتباط یک اپلیکیشن نمونه و ساده را هم با appinventor اجرا کنید

    • سلام متشکرم
      در تخصص بنده نیست امیدوارم سایر دوستان آموزش درخواستی شما را منتشر کنند.

    • سلام خسته نباشید
      برای ارسال دیتاازطریق بلوتوث هم کدی هست که بتونید در اختیارمون قرار بدید؟ مشکل اپ ما این هست که دیتارو از سمت اردوینو بد دریافت میکنه و نمیتونه مقادیر رو در فیلدهای مربوطه جا بده و مشکل داره

      • سلام وقت بخیر
        بنده کدی نوشته ندارم. اگه اپ داره درست ارسال میکنه پس مشکل از سمت آردوینو هست. دیتایی که وارد آردوینو میشه رو پرینت کنید تا مشخص بشه مشکلش کجاست.

        • نه مشکل اینجاست وقتی با یک اپ مقد ترمینال بلوتوث کارمیکنیم متوجه میشیم دیتا به درستی از سمت اردوینو ارسال و دریافت میشه اما وقتی با اپ خودمون تست میکنیم این اتفاق نمیفته و نمیدونیم کدوم قسمت از کدهای اپ رو باید تغییر بدیم

  • سلام خدمت شما من این آپ و راه اندازی کردم ولی گوشیم اندروید ۱۱ و هیچ عکس العملی نشون نمیده
    ولی نسخه های پایین تر مثل ۴٫۴ که گوشی قدیمیمه جواب میده میشه راهنمایی کنین واسه نسخه بالاتر چیکار باید بکنم ؟
    سلام من هم دقیقا این مشکل را دارم بنظر شما مشکل از چیست

    • با سلام خدمت شما
      احتمالا کتابخانه های استفاده شده در ورژن های جدیدتر ساپورت نمیشوند یا باید از نسخه جدید آنها استفاده کنید.