用了几天写成的码表,决定开个源
用328做mcu,ds1307做时钟功能,44e霍尔元件,5110做显示
目前有速度、单次时间、单次里程、总里程、时间显示
设置我采用红外遥控进行,CH+和CH-可以调车轮半径,按EQ进入时间设置,EQ切换,加、减、快进、快退用来调增减
关于电池:
我直接用手机锂电池供电(3.7v),背光关闭电流32ma,背光开启电流42ma,一个电池用几天不是问题
电路以及用到的库在帖子最后面提供下载,我采用了单层pcb,便于大家自己制作
你需要遵循如下协议:
#include "U8glib.h"
#include <Wire.h>
#include <EEPROM.h>
#include <DS1307.h>
#include <IRremote.h>
#define zdpin 1
#define timeOUT 3000 //检测速度超时
#define EEPDELAY 5000 //EEPROM更新检测
#define refresh 5 //刷新圈数
#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp);}
#define EEPROM_read(address, p){int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp=EEPROM.read(address+i);}
#define jsLCDa 2000 //设置时显示时间
boolean lcda = false;
long TIMELCDa;
int LCDSW=0;
int R; //cm
boolean Rsetup,Rsetdown;
long CACHEDELAY;
int Reep; //xxeep判断数值是否更改,set为设置值
float MILEeep;
struct config_type
{
int EEPROMMILE;
int EEPROMMILEs;
int EEPROMR;
};
/*-------lcd------*/
U8GLIB_PCD8544 u8g(5, 6, 8, 7, 9); // SPI Com: CLK = 5, DIN = 6, CE = 8, DC = 7, Reset = 9
int num;
float SPEED;
float ALLMILE;
float ONEMILE,ONEMILEcache;
long RPM;
/*------计时-----*/
long timea,timeb;
long time,timecache;
boolean timeSTA;
/*----time----*/
String comdata = "";//串口数据缓存
int numdata = {
0}
, j = 0, mark = 0;
int rtc;
int TIMEshi, TIMEfen, TIMEmiao; //时钟
#define SHEtimeOUT 6000
int sheshi, shefen;
int shenum;
booleanshesta = false, shesw, sheDOWN = false, sheUP = false;
long SHEtime;
/*----MENU----*/
#define MENUtimeOUT 5000
boolean MENUsta = false, MENUsw = false, MENUup = false, MENUdown = false, MENUup10x = false, MENUdown10x = false;
int MENUswNUM = 0;
long MENUtime;
/*-------ir------*/
int RECV_PIN = A0; //红外输入
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup ()
{
Serial.begin(9600);
/*EEPROM读取赋值*/
config_type config_readback;
EEPROM_read(0, config_readback);
ALLMILE = float(config_readback.EEPROMMILE+(config_readback.EEPROMMILEs/10.0));
MILEeep = config_readback.EEPROMMILE;
R = config_readback.EEPROMR;
Reep = config_readback.EEPROMR;
attachInterrupt(zdpin,light,FALLING); //检测中断
CACHEDELAY=millis();
ONEMILEcache=ALLMILE;
RTC.SetOutput(DS1307_SQW32KHZ);
irrecv.enableIRIn(); //开始采集
}
void loop()
{
Rsetup = false;
Rsetdown = false;
MENUup = false;
MENUdown = false;
MENUup10x = false;
MENUdown10x = false;
MENUsw = false;
shesw=false;
RTC.get(rtc, true);
TIMEshi = rtc;
TIMEfen = rtc;
TIMEmiao = rtc;
/*=================红外控制=================*/
if (irrecv.decode(&results))
{
voir();
}
/*=======码表=======*/
if(num>refresh)
{
jisuan();
timea=millis();
num=1;
}
ONEMILE=ALLMILE-ONEMILEcache;
if(millis()-timeb>timeOUT)
{
RPM=0;
SPEED=0;
timeSTA=false;
timecache=millis()-time;
}
else
{
timeSTA=true;
time=millis()-timecache;
}
if(ALLMILE>9999)
{
ALLMILE=0;
}
/*==========EEPROM==========*/
if (millis() - CACHEDELAY > EEPDELAY)
{
if(MILEeep != ALLMILE||Reep!=R) //判断EEPROM是否有改变
{
eeprom_write();
MILEeep = ALLMILE;
Reep = R;
}
CACHEDELAY=millis();
}
/*==============半径设置=================*/
if(Rsetup==true)
R++;
if(Rsetdown==true)
R--;
if(R>60)
R=10;
if(R<10)
R=60;
/*==================Time======================*/
if(shesta == true) //进入设置状态
{
voshe();
}
if(shesw == true) //切换
shenum++;
if(shenum > 2) //范围
shenum = 1;
RTC.get(rtc, true);
TIMEshi = rtc;
TIMEfen = rtc;
TIMEmiao = rtc;
if (sheshi > 23)
{
sheshi = 1;
}
if (sheshi < 0)
{
sheshi = 23;
}
if (shefen > 59)
{
shefen = 0;
}
if (shefen < 0)
{
shefen = 59;
}
/*===========LCD===========*/
if(Rsetup == true || Rsetdown == true) //触发
{
TIMELCDa = millis();
lcda = true;
}
if(lcda == true)
{
voLCDdelay();
}
u8g.firstPage();
do {
draw();
}
while( u8g.nextPage() );
}
void jisuan()
{
ALLMILE+=((float(refresh)*(2.0*3.1416*(R/100.0))))/1000.0; //总里程累加
RPM=60000/((millis()-timea)/refresh); //转速
SPEED=((RPM*(2.0*3.14159*(R/100.0)))*60.0)/1000.0; //速度
}
void light() //计数
{
num++;
timeb=millis();
}
void eeprom_write()
{
config_type config; // 定义结构变量config,并定义config的内容
config.EEPROMMILE = int(ALLMILE);
config.EEPROMMILEs = int(ALLMILE*10)%10;
config.EEPROMR = R;
EEPROM_write(0, config); // 变量config存储到EEPROM,地址0写入
}
void voadd(int add)
{
if (add < 10)
u8g.print("0");
}
void voLCDdelay() //显示超时
{
if (millis() - TIMELCDa > jsLCDa && lcda == true) //设置刷新频率
{
lcda = false;
}
}
void voir()
{
unsigned long remote = results.value; //设红外信号为remote
if(remote == (-1)) //溢出时
{
Serial.print(results.value, HEX); //输出红外线解码结果(十六进制)
}
switch (remote)
{
case 0xFFE21D: //CH+
Rsetup = true;
LCDSW=1;
break;
case 0xFFA25D: //CH-
Rsetdown = true;
LCDSW=1;
break;
case 0xFF906F: //EQ
shesw = true;
voshe();
voshesta();
break;
case 0xFFE01F: //-
MENUdown = true;
break;
case 0xFFA857: //+
MENUup = true;
break;
case 0xFF22DD: //PREV
MENUdown10x = true;
break;
case 0xFF02FD: //NEXT
MENUup10x = true;
break;
}
irrecv.resume(); // 返回值
}
void draw() {
u8g.drawLine(51, 0, 51, 10);
u8g.drawLine(0, 11, 83, 11);
u8g.drawLine(0, 29, 83, 29);
u8g.drawLine(0, 39, 83, 39);
u8g.setFont(u8g_font_6x13Br);
u8g.setPrintPos(0, 9);
voadd(int(SPEED*10)/10);
u8g.print(int(SPEED*10)/10); //SPEED
u8g.print(".");
u8g.print(int(SPEED*10)%10);
u8g.print(" KPH");
u8g.setPrintPos(54, 8);
if(shesta == true) //进入设置状态
{
u8g.setFont(u8g_font_6x12);
switch(shenum)
{
case 1:
{
if((millis() / 1000) % 2 != 0)
{
voadd(sheshi);
u8g.print(sheshi);
}
else
u8g.print("");
u8g.print(":");
voadd(shefen);
u8g.print(shefen);
}
;
break;
case 2:
{
voadd(sheshi);
u8g.print(sheshi);
u8g.print(":");
if((millis() / 1000) % 2 != 0)
{
voadd(shefen);
u8g.print(shefen);
}
else
{
u8g.print(" ");
}
}
;
break;
}
}
else //正常显示时间
{
u8g.setFont(u8g_font_6x12);
voadd(TIMEshi);
u8g.print(TIMEshi); //hou
if(millis()/1000%2!=0)
u8g.print(":");
else
u8g.print(" ");
voadd(TIMEfen);
u8g.print(TIMEfen); //min
}
u8g.setPrintPos(0, 26);
u8g.setFont(u8g_font_6x13);
u8g.print("ONCE");
u8g.setFont(u8g_font_chikitar);
u8g.print(": ");
u8g.setPrintPos(28, 20);
{
u8g.setFont(u8g_font_fixed_v0r);
voadd(ONEMILE);
u8g.print((int)ONEMILE); //单次里程
u8g.print(".");
u8g.print(int(ONEMILE*10)%10);
u8g.print(int(ONEMILE*100)%10);
u8g.print("km");
}
u8g.setPrintPos(28, 28);
{
u8g.setFont(u8g_font_fixed_v0r);
voadd(time/1000/60/60);
u8g.print(time/1000/60/60); //单次时间
u8g.setFont(u8g_font_chikitar);
u8g.print("hr");
u8g.setFont(u8g_font_fixed_v0r);
voadd(time/1000/60%60);
u8g.print(time/1000/60%60);
u8g.setFont(u8g_font_chikitar);
u8g.print("min");
}
{
u8g.setFont(u8g_font_chikitar);
u8g.setPrintPos(0, 37);
u8g.print("MILE: "); //总里程
u8g.setPrintPos(26, 38);
u8g.setFont(u8g_font_fixed_v0r);
if(int(ALLMILE*10)/10<10)
{
u8g.print("000");
}
if(int(ALLMILE*10)/10>10 && int(ALLMILE*10)/10<100)
{
u8g.print("00");
}
if(int(ALLMILE*10)/10>100 && int(ALLMILE*10)/10<1000)
{
u8g.print("0");
}
u8g.print(int(ALLMILE));
u8g.print(".");
u8g.setFont(u8g_font_fixed_v0r);
u8g.print(int(ALLMILE*10)%10);
u8g.setFont(u8g_font_chikitar);
u8g.print("km");
}
u8g.setFont(u8g_font_chikitar);
u8g.setPrintPos(1, 46);
if (lcda == true) //半径设置
{
if(LCDSW==1)
{
u8g.print("Wheel radius: ");
voadd(R);
u8g.print(R);
u8g.print("cm");
}
}
else
{
u8g.print("--Design By PKJ--");
}
}
void voshe()
{
if(shenum == 0) //初始赋值
{
sheshi = TIMEshi;
shefen = TIMEfen;
}
RTC.stop(); //准备写入时间
if(millis() - SHEtime > SHEtimeOUT) //超时
{
shesta = false; //退出设置
shenum = 0; //初始
RTC.set(DS1307_HR, sheshi);
RTC.set(DS1307_MIN, shefen);
RTC.set(DS1307_SEC, 0);
RTC.start();
}
if(MENUup == true || MENUdown == true || MENUup10x == true || MENUdown10x == true) //触发时
{
voshesta();
}
switch(shenum) //按键作用
{
case 1:
{
if(MENUup == true)
{
sheshi++;
}
if(MENUdown == true)
{
sheshi--;
}
if(MENUup10x == true)
{
sheshi += 10;
}
if(MENUdown10x == true)
{
sheshi -= 10;
}
};
break;
case 2:
{
if(MENUup == true)
{
shefen++;
}
if(MENUdown == true)
{
shefen--;
}
if(MENUup10x == true)
{
shefen += 10;
}
if(MENUdown10x == true)
{
shefen -= 10;
}
};
break;
}
}
void voshesta() //触发时间设置状态
{
SHEtime = millis();
shesta = true;
}
好东西,顶一个! 好东西!谢谢楼主!
另外请问楼主速度传感器用的什么?总共就是一个霍尔原件吗? fangtaonj 发表于 2013-4-7 11:14 static/image/common/back.gif
好东西!谢谢楼主!
另外请问楼主速度传感器用的什么?总共就是一个霍尔原件吗?
一个霍尔,一个磁钢 LZ我也想做一个 本人刚刚接触代码 看着晕 可以简化一下不要时间和红外吗,直接显示速度 踏频 里程 平均速度就可以了 ,轮子周长设置可以直接放在代码里 楼主是整合成了一个pcb板子么,是参考那个arduino的线路呢 哇,不错哦!!! duocool 发表于 2013-4-7 15:56 static/image/common/back.gif
楼主是整合成了一个pcb板子么,是参考那个arduino的线路呢
这个你可以参考一下官网的promini,除去下载部分,就可以算最小系统了,我另外加了asp刷机插座:http://arduino.cc/en/Main/ArduinoBoardProMini 本帖最后由 wasdpkj 于 2013-4-7 23:56 编辑
Athlon 发表于 2013-4-7 13:59 static/image/common/back.gif
LZ我也想做一个 本人刚刚接触代码 看着晕 可以简化一下不要时间和红外吗,直接显示速度 踏频 里程 平均速度 ...
那我给你一个基础代码,1602做显示,最基本的功能:
#include <LiquidCrystal.h>
#include <EEPROM.h>
#define zdpin 0
#define timeOUT 3000 //超时
#define R 300 //轮子半径
#define DEFY 1 //安装几个霍尔
#define EEPDELAY 5000
#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp);}
#define EEPROM_read(address, p){int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp=EEPROM.read(address+i);}
long CACHEDELAY;
int MILEeep; //xxeep判断数值是否更改,set为设置值
struct config_type
{
float EEPROMMILE;
};
/*-------lcd------*/
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);//设置接口
int num;
float SPEED;
float ALLMILE;
long RPM;
long timea,timeb;
long time,timecache;
boolean timeSTA;
void setup ()
{
Serial.begin(9600);
/*EEPROM读取赋值*/
config_type config_readback;
EEPROM_read(0, config_readback);
MILEeep = config_readback.EEPROMMILE;
ALLMILE = config_readback.EEPROMMILE;
attachInterrupt(zdpin,light,FALLING); //?ж?
lcd.begin(16, 2); //初始化LCD
lcd.print(" ===Via--PKJ=== "); //显示文字
delay(600); //延时
lcd.clear();
CACHEDELAY=millis();
}
void loop()
{
if(num>9)
{
jisuan();
timea=millis();
num=0;
}
if(millis()-timeb>timeOUT)
{
RPM=0;
SPEED=0;
timeSTA=false;
timecache=millis()-time;
}
else
{
timeSTA=true;
time=millis()-timecache;
}
if (millis() - CACHEDELAY > EEPDELAY)
{
if(MILEeep != ALLMILE) //判断EEPROM是否有改变
{
eeprom_write();
MILEeep = ALLMILE;
}
CACHEDELAY=millis();
}
lcd.setCursor(0, 0) ; //设置光标位置
lcd.print("RPM:");
lcd.print(RPM);
lcd.print(" ");
lcd.setCursor(8, 0) ;
lcd.print("SPE:");
if(int(SPEED*10)/10<10)
{
lcd.print("0");
}
lcd.print(int(SPEED*10)/10);
lcd.print(".");
lcd.print(int(SPEED*10)%10);
lcd.print("");
lcd.setCursor(0, 1) ;
if(int(ALLMILE*10)/10<10)
{
lcd.print("00");
}
if(int(ALLMILE*10)/10>10 && int(ALLMILE*10)/10<100)
{
lcd.print("0");
}
lcd.print(int(ALLMILE*10)/10);
lcd.print(".");
lcd.print(int(ALLMILE*10)%10);
lcd.print("KM");
lcd.setCursor(8, 1);
lcdout(time/1000/60/60); //使屏幕显示文字
lcd.print(time/1000/60/60); //使屏幕显示文字
lcd.setCursor(10, 1);
lcd.print(":"); //使屏幕显示文字
lcdout(time/1000/60%60); //使屏幕显示文字
lcd.print(time/1000/60%60); //使屏幕显示文字
lcd.setCursor(13, 1);
lcd.print(":"); //使屏幕显示文字
lcdout(time/1000%60); //使屏幕显示文字
lcd.print(time/1000%60); //使屏幕显示文字
Serial.println(RPM);
Serial.println("");
}
void jisuan()
{
ALLMILE=((((10.0*(2.0*3.14159*(R/1000.0))))/1000.0)/DEFY)+ALLMILE;
RPM=(600000/((millis()-timea)))/DEFY;
SPEED=((RPM*(2.0*3.14159*(R/1000.0)))*60.0)/1000.0;
}
void light()
{
num++;
timeb=millis();
}
void lcdout(int lcdOUT)
{
if(lcdOUT<10)
{
lcd.print("0");
}
}
void eeprom_write()
{
config_type config; // 定义结构变量config,并定义config的内容
config.EEPROMMILE = ALLMILE;
EEPROM_write(0, config); // 变量config存储到EEPROM,地址0写入
}
请问楼主用的哪款软件设计的板子呢,只能弄弄洞洞板,希望有天也能做个整合的板子 duocool 发表于 2013-4-8 09:48 static/image/common/back.gif
请问楼主用的哪款软件设计的板子呢,只能弄弄洞洞板,希望有天也能做个整合的板子
eagle........... 楼主你好,PCB是一张空白啊,什么都没有,你用什么画的? 楼主你好,PCB是一张空白啊,什么都没有,你用什么画的? zfm0610363 发表于 2013-4-8 20:01 static/image/common/back.gif
楼主你好,PCB是一张空白啊,什么都没有,你用什么画的?
eagle,挺好用的 楼主你好,PCB是一张空白啊,什么都没有,你用什么画的?
页:
[1]
2