Speedometer for a skate. Hopelessness

Background


Good day.
One fine summer evening, in search of something long forgotten, but fascinating, I sorted out things in boxes. Having glanced at the last, already slightly desperate, I nevertheless found an interesting thing. It was a Chinese speedometer for a bicycle. Of course, the microcomputer was not there - which is not surprising (in childhood, thanks to my curiosity, most of the things I examined were not collected and were simply simply thrown away). But this was not the only problem - I do not have a bicycle. He was taken by his older brother, and I myself ride a skateboard. So the idea arose of what to do with yourself!

Under the cut a lot of photos.

Components


Skate

Since I don’t perform any stunts on a skateboard, I ride a cruiserboard for my own pleasure and it’s interesting: “how much did I ride?”.

Cruiserboard photo


Smart watch

For the New Year, I bought myself from the Chinese these watches:

Smartwatch Photos


This is a SmartQ smartwatch called the Z-Watch. They are divided into the older (Z1) and younger (Z1-Lite) model. The difference is that in the younger model there is no: Wi-fi module, eMMC flash memory 512Mb (in the older 4Gb), 256Mb RAM (in the older 512Mb). The watch is equipped with a 1.54-inch TFT LCD screen with a resolution of 240x240 pixels, an Ingenic JZ4775 processor with a frequency of 1.0Ghz, Bluetooth 4.0 BLE, Wi-fi IEEE 802.11 b / g / n, an accelerometer, waterproof IP-X7 (3 ATM), Li battery -poly at 300mAh, OS Android 4.4 KitKat (simplified).

Arduino Mini Pro

Microcontroller Arduino Pro Mini:

Photo Arduino Pro Mini


It was chosen simply because it was at hand. Will count the number of revolutions of the wheel.

Bluetooth HC-06

Bluetooth module with which we will communicate with our watch:

Bluetooth module photo



Reed sensor

Sensor from a Chinese speedometer for a bicycle:

Sensor Photo



Battery

Samsung Battery 3.7V, 1000mAh:
Battery Photo



Assembly


Scheme of our device:
Speedometer circuit


I think no comments are needed. Of course, the LED should be connected through a transistor - then there would be more light, but this is not so important. I put together a prototype on a breadboard. It has a bottom piece of double-sided tape on which I attached the battery. I did not cut off the sensor mount to the handlebars of the bicycle, since in the future I can get, respectively, a bicycle :)
Prototype photo




I mounted the sensor with the reed switch on the suspension using the flagella:

Photo of the bottom of the skateboard


The LED below was attached to check the data transfer from the clock to the microcontroller. Suitable as a backlight at night.
I drilled a shallow hole in the wheel and secured a neodymium magnet in it (pulled it out of the old drive):

Photo of a wheel with a magnet



Software part


I am not good at programming, but I will be very glad in the advice on this!

Microcontroller

volatile long cntr;
boolean flip;
boolean yes = false;
int rev = 0;
void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  pinMode(12, INPUT);
  TCCR2A = 0; 
  TCCR2B = 2;
  TCNT2 = 59;
  TIMSK2 |= (1 << TOIE2); 
}
ISR(TIMER2_OVF_vect) {
  TCNT2 = 59;//55;
  cntr++;
  if(cntr>9999) 
  {
    flip = true;
    cntr = 0;
  }
}
void loop() 
{
  if (flip) 
  {
    Serial.println(String(rev)+';');
    rev = 0;
    flip = false;
  }  
  else
  {
    if (digitalRead(12) == HIGH) 
    {
      if (yes)
      {
        rev++;
        yes = false;
      }
    } else yes = true;
  }
  if (Serial.available() > 0){
    char command = Serial.read();
    switch(command){
      case '0': digitalWrite(13, LOW); break;
      case '1': digitalWrite(13, HIGH); break;
    }
  }
}


The essence of the program

While the timer is ticking, the number of revolutions is counted in the main cycle and commands from the clock, if any, are processed. After a second, the controller sends the number of revolutions to the clock, i.e. we have a frequency (r / c).

Clock

The code was taken from this article and added a little.
The code
AndroidManifest.xml



FullscreenActivity.java

package com.example.admin.speedometer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.UUID;
import com.example.admin.speedometer.R;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.bluetooth.*;
import android.content.Intent;
public class FullscreenActivity extends Activity {
    private static final int REQUEST_ENABLE_BT = 1;
    final int ArduinoData = 1;
    final String LOG_TAG = "myLogs";
    private BluetoothAdapter btAdapter = null;
    private BluetoothSocket btSocket = null;
    private StringBuilder sb = new StringBuilder();
    private static String MacAddress = "20:13:05:07:01:97"; // MAC-адрес БТ модуля
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    private ConnectedThred MyThred = null;
    public TextView spdtext, distext, fromarduino;
    public double Distance = 0;
    Button b1, b2;
    Handler h;
    /*
    Settings:
     */
    private static double Radius = 3.0; //радиус колеса в сантиметрах
    private static double spdUnit = 3.6; //размерность скорости: 3.6 в км/ч, 1.0 в м/c
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fullscreen);
        btAdapter = BluetoothAdapter.getDefaultAdapter();
        spdtext = (TextView) findViewById(R.id.textView1);
        distext = (TextView) findViewById(R.id.textView2);
        fromarduino = (TextView) findViewById(R.id.textView5);
        if (btAdapter != null){
            if (btAdapter.isEnabled()){
                //mytext.setText("Bluetooth включен. Все отлично.");
            }else
            {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            }
        }else
        {
            MyError("Fatal Error", "Bluetooth ОТСУТСТВУЕТ");
        }
        b1 = (Button) findViewById(R.id.button1);
        b2 = (Button) findViewById(R.id.button2);
        b1.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                MyThred.sendData("1");
            }
        });
        b2.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                MyThred.sendData("0");
            }
        });
        h = new Handler() {
            public void handleMessage(android.os.Message msg) {
                switch (msg.what) {
                    case ArduinoData:
                        byte[] readBuf = (byte[]) msg.obj;
                        String strIncom = new String(readBuf, 0, msg.arg1);
                        sb.append(strIncom);
                        int endOfLineIndex = sb.indexOf("\r\n");
                        if (endOfLineIndex > 0) {
                            String sbprint = sb.substring(0, endOfLineIndex);
                            sb.delete(0, sb.length());
                            String value = "";
                            byte channel = 0; //используется если команд несколько: 0;0;0;
                            fromarduino.setText("Arduino: " + sbprint);
                            for (int i = 0; i < sbprint.length(); i++) {
                                if (sbprint.charAt(i) == ';')  {
                                    if (!value.isEmpty()) {
                                        switch (channel) {
                                            case 0:
                                                double Dis = (Double.parseDouble(value) * (Radius * 6.28) )  / 100.0;
                                                double Speed = Dis * spdUnit;
                                                spdtext.setText(String.valueOf(Math.round(Speed)));
                                                Distance += Dis;
                                                distext.setText(String.valueOf(Math.round(Distance)));
                                                break;
                                        }
                                    }
                                    value = "";
                                    channel++;
                                } else value += sbprint.charAt(i);
                            }
                        }
                        break;
                }
            };
        };
    }
    @Override
    public void onResume() {
        super.onResume();
        BluetoothDevice device = btAdapter.getRemoteDevice(MacAddress);
        Log.d(LOG_TAG, "***Получили удаленный Device***"+device.getName());
        try {
            btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
            Log.d(LOG_TAG, "...Создали сокет...");
        } catch (IOException e) {
            MyError("Fatal Error", "В onResume() Не могу создать сокет: " + e.getMessage() + ".");
        }
        btAdapter.cancelDiscovery();
        Log.d(LOG_TAG, "***Отменили поиск других устройств***");
        Log.d(LOG_TAG, "***Соединяемся...***");
        try {
            btSocket.connect();
            Log.d(LOG_TAG, "***Соединение успешно установлено***");
        } catch (IOException e) {
            try {
                btSocket.close();
            } catch (IOException e2) {
                MyError("Fatal Error", "В onResume() не могу закрыть сокет" + e2.getMessage() + ".");
            }
        }
        MyThred = new ConnectedThred(btSocket);
        MyThred.start();
    }
    @Override
    public void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "...In onPause()...");
        if (MyThred.status_OutStrem() != null) {
            MyThred.cancel();
        }
        try     {
            btSocket.close();
        } catch (IOException e2) {
            MyError("Fatal Error", "В onPause() Не могу закрыть сокет" + e2.getMessage() + ".");
        }
    }
    private void MyError(String title, String message){
        Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show();
        finish();
    }
    //Отдельный поток для передачи данных
    private class ConnectedThred extends Thread{
        private final BluetoothSocket copyBtSocket;
        private final OutputStream OutStrem;
        private final InputStream InStrem;
        public ConnectedThred(BluetoothSocket socket){
            copyBtSocket = socket;
            OutputStream tmpOut = null;
            InputStream tmpIn = null;
            try{
                tmpOut = socket.getOutputStream();
                tmpIn = socket.getInputStream();
            } catch (IOException e){}
            OutStrem = tmpOut;
            InStrem = tmpIn;
        }
        public void run()
        {
            byte[] buffer = new byte[1024];
            int bytes;
            while(true){
                try{
                    bytes = InStrem.read(buffer);
                    h.obtainMessage(ArduinoData, bytes, -1, buffer).sendToTarget();
                }catch(IOException e){break;}
            }
        }
        public void sendData(String message) {
            byte[] msgBuffer = message.getBytes();
            Log.d(LOG_TAG, "***Отправляем данные: " + message + "***"  );
            try {
                OutStrem.write(msgBuffer);
            } catch (IOException e) {}
        }
        public void cancel(){
            try {
                copyBtSocket.close();
            }catch(IOException e){}
        }
        public Object status_OutStrem(){
            if (OutStrem == null){return null;
            }else{return OutStrem;}
        }
    }
}



The essence of the program

The program receives data from the microcontroller about the wheel speed. In order to get the correct information, you need to measure the radius of the wheel, then the program will find its circumference and will calculate the speed and distance. You need to adjust the radius of the wheel and in what units the speed will be displayed:
/*
Settings:
*/
private static double Radius = 3.0; //радиус колеса в сантиметрах
private static double spdUnit = 3.6; //размерность скорости: 3.6 в км/ч, 1.0 в м/c

N - number of revolutions;
l is the circumference;
t - time (since we count once a second - this value can be neglected);
l = 2pr is the circumference;
S = V * t = (N * l) / 100 - the distance that we traveled in 1 second (expressed in meters);
double Dis = (Double.parseDouble(value) * (Radius * 6.28)) / 100.0;

V = S / t = S * 3.6 - speed (expressed in km / h).
double Speed = Dis * spdUnit;

There are also two buttons on. and off LED, which is located on the bottom of the skateboard.

Conclusion

There are some errors, but overall I am satisfied with the result. Thanks sychidze for the article!
Video work will be a little later.

Also popular now: