5iMX宗旨:分享遥控模型兴趣爱好

5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
查看: 23265|回复: 101
打印 上一主题 下一主题

数显卡尺 三轴显示表头 2011/2/28更新 基本搞定。除了外壳

[复制链接]
跳转到指定楼层
楼主
发表于 2009-11-21 23:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
厄。。。。写了半天。。 结果告诉我附件大回来写的都没了。。。。。。。。。。。。。。。。。。。。。!!!


用的Arduino方案 板子大概100来块钱, 其实可以用最小系统,一个AVR单片机+个晶振就可以工作了。

电阻四个 NPN三极管2只 电容一个 1602屏幕一个 卡尺一只

卡尺数据就是做加法。。。 远远比先前几位老大哥整的简单许多。

不过下一把卡尺就不知道是否是这种结构了。

[ 本帖最后由 thirty 于 2011-2-28 02:39 编辑 ]

DSC05605.jpg (83.14 KB, 下载次数: 196)

DSC05605.jpg

数据.jpg (97.81 KB, 下载次数: 180)

数据.jpg

评分

参与人数 8威望 +16 模币 +1 收起 理由
兰竹 + 2 + 1 感谢分享!
ncmaker + 2 【精品文章】感谢分享希望继续努力发更多更 ...
量具王子 + 2 【精品文章】感谢分享希望继续努力发更多更 ...
如此执着 + 2 【精品文章】感谢分享希望继续努力发更多更 ...
大白兔 + 2 强了支持30,可惜只能加2分

查看全部评分

欢迎继续阅读楼主其他信息

沙发
 楼主| 发表于 2009-11-21 23:36 | 只看该作者
不会单片机也能搞定卡尺读数据 哇卡卡。。。
3
发表于 2009-11-21 23:36 | 只看该作者
:em26:
4
发表于 2009-11-21 23:58 | 只看该作者
:em20:
5
发表于 2009-11-22 07:06 | 只看该作者
祝贺30!多日的辛勤付出,终于修成正果!
6
发表于 2009-11-22 08:41 | 只看该作者
先支持一下,lz能详细的解说就更好了。:em21:
7
发表于 2009-11-22 08:56 | 只看该作者
恭喜恭喜!:em26: :em26: :em26:
8
 楼主| 发表于 2009-11-22 20:10 | 只看该作者
hcheng 谢谢评分哦!!treo600v 我不知道如何介绍的更详细了,呵呵因为很简单。介绍一下Arduino吧
Arduino其实就是在AVR单片机的基础上,吧基本上所有的功能就封装为简单的语言。类似于java。近似于我工作用的语言。所以用起来还还算好。
比如给1602输入数据就是简单的初始化一下1602以后 输入 lcd.print("你要写的文字") 就行了。

Arduino可以做很多事,配套的类库也很多。比如直接操作DC MOTOR, 步进电机,伺服电机。等等。。。

要是有光栅尺 相信读取光栅尺的数据也是很简单的。
9
 楼主| 发表于 2009-11-22 20:12 | 只看该作者
int clkPin = 2; //定义时钟脚位
int dataPin = 3;//定义数据脚位
int debugPin = 13;//定义测试LED脚位
int clk;//时钟
int data;//数据
int debug;//测试
int x = 0;//x轴循环
int data1[24]={};//存放X轴24个数据的数组
float cal[20]={0.01,0.02,0.04,0.08,0.16,0.32,0.64,1.28,2.56,5.12,10.24,20.48,40.96,81.92,163.84,327.68,655.36,1310.72,2621.44};//存放20位对应数值的数组
float xData;//最终要输出的数据
boolean isRead1 = true;//判断X轴是否空闲
//LCD
#include <LiquidCrystal.h>//导入驱动16x2的类库
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);//定义16x2脚位四线驱动,(还可以用I2C驱动)。脚位定义(RS,EN,DB4,DB5,DB6,DB7)
//

void setup(){//构造函数,初始化的时候执行一次。
  Serial.begin(9600);//打开串口,波特率为9600可以连接PC,读取Arduino送出的数据。
  lcd.begin(16,2);//初始化16x2,好似也可以初始化16x4。
  //lcdInit();//本来是初始化lcd的,有BUG目前没用。
  pinMode(clkPin,INPUT);//时钟针脚输入模式为输入
  pinMode(dataPin,INPUT);//数据针脚输入模式为输入
  pinMode(debugPin,OUTPUT);//测试针脚为输出 板子上有个专门测试的LED
}
void loop(){//循环函数,按照晶振的速度进行循环好似是,我不大懂。晶振是16M的。如果用AVR单片机内置的晶振做最小系统,那么就是8M的
    clk = digitalRead(clkPin);//读取时钟针脚确定电平
    if(clk){//如果电平为1 这里吧高电平和低电平当布尔值来用
      isRead1 = false;//标记X轴为不空闲 -=Mark 1=-
    }else{
      readData1();//如果时钟脚位为“假”,那么执行此方法。
    };  
}

void readData1(){//自定义方法
  if(!isRead1){//此处配合标记 -=Mark 1=- ,目的是低电平转为高电平的只读一次。如果不这么做。那会在一瞬间读出来n个0或者1数据不正确。
    digitalWrite(debugPin,HIGH);//打开Debug灯
    //delayMicroseconds(50);//延迟,后来发现没啥意义。注释掉了
    data1[x] = abs(digitalRead(dataPin)-1);//吧负逻辑转换为正逻辑,为了减少电路,只用了一个三极管儿做电平转换,所以逻辑是反的。就是卡尺输出1的时候实际上Arduino读到的是0,所以需要转换一下。
    x++;//x计数器自变量+1。
    isRead1=true;//标记X轴为空闲准备读取下一位数据。
    if(x == 23){//如果已经读了24次,0也算一次的。
    xData = 0;//输出给16x2的数据先初始化为0。
    for(int i = 0; i < 20;i++){//跑一个循环,读数组的前20位。 后面四位暂不读取。
        xData += data1 * cal;//左边的意思是,将要输出的数据 += X轴数据的[第i位] * 存放对应数值的数组[的第i位置]
        //接上面,i总共会从0+到99,正好读出20个位数。而吧这些数字相加。得数就是卡尺显示的数据了。因为X轴数据实际上是0 和 1,这就是简单的数学题了。
    }
    if(data1[20]){//判断data1的21为是否为1,0也算一位的哦。如果是1,那么卡尺输出是负数的。
      xData*=-1;//当然也要吧要显示给16x2的数字转换为负数的。
    };
    lcdPrint();//然后lcd打印
    //Serial.println(xData);//这里是串口输出可以给pc看数值,因为占用机器周期太多了。就给关了。
    x = 0;//读取输出都搞定了,x轴循环清零。
    };
    digitalWrite(debugPin,LOW);//一次读取输出完毕,关闭debug LED。
  };
};
void lcdInit(){//自定义方法lcd初始化,目前没用。
}
void lcdPrint(){//自定义方法输出16x2数据。
   lcd.print("X_axle = ");//首先打上这些文字
   lcd.setCursor(5,1);//然后移动到第二行第五个字符位上
   lcd.print("THirTy");//打出我的名字
   lcd.setCursor(9,0);//然后在移动到第一行第九个字符位 -_-...神经。。。来回移。。。等会改了。。。
   lcd.print(xData);//打印x轴数据
   lcd.print("   ");//然后接着x轴数据后面打三个空格。不然数字丛大到小的时候会留下一些数字覆盖不到。
   //lcd.clear();//清屏,后来注释掉了。加上以后屏幕全部频繁刷新,有闪烁感。
}

没了。。。就这么简单。。。
10
发表于 2009-11-22 20:35 | 只看该作者
不错,恭喜楼主。最好卡尺改为快速采样,不然显示有点慢。:em15:


感兴趣的是那个兰色的PCB
是直接买来的吗?哪里有卖的?多少钱?是AVR的最小系统做的成品板还是....

[ 本帖最后由 NOMO012000 于 2009-11-22 20:39 编辑 ]
11
 楼主| 发表于 2009-11-22 22:43 | 只看该作者
这算是arduino开发板吧。 还不是最小系统。这算是完全的 有完整的输入 输出 调试功能。
我的理解是最小系统只需要吧这个avr启动便可。而启动avr单片机只要5v电源和晶振貌似就行。晶振都可以不要。
taobao上便有出售。 搜寻Arduino就行了。 国外www.arduino.cc 完全开源的 可以下pcb 什么的自制。
taobao上最便宜的我这样的板子85块钱
12
发表于 2009-12-9 02:15 | 只看该作者
LZ可否把Arduino和 数显卡尺之間的連|接電路上圖看看, 謝謝.
13
 楼主| 发表于 2009-12-27 18:09 | 只看该作者
卡尺 之间的电路现在已经换了 电平转换用了一只IC.. 这样就省事儿很多了。。 然后用了一个LM317给卡尺供电
到时候我上个模拟图、、
14
发表于 2010-5-18 19:38 | 只看该作者
做的好!
15
发表于 2010-7-7 16:44 | 只看该作者
可以介绍一下卡尺里面的接线吗,
16
发表于 2010-12-21 23:05 | 只看该作者
谢谢LZ的好资料呀,我也写了个程序, 串口输出:
与楼主有些不同
用中断
直接输出至串口
支持 公英制  自动判别
在LOOP中的输出部分 由于 有了公英制 复杂了些,为了显示4位小数,就在程序中用了整数
输出时再处理小数点。


///////////////////////////////////////////////////
//电子尺读数
//   gnd  data  clk  vcc1.5
// Pin Declarations
int dataIn = 3;
int clockIn = 2;

int isin=0; //英寸=1,mm=0
int isfs=0;  //是负数
int index;
//float cal[20]={0.01,0.02,0.04,0.08,0.16,0.32,0.64,1.28,2.56,5.12,10.24,20.48,40.96,81.92,163.84,327.68,655.36,1310.72,2621.44,5242.88};//存放20位对应数值的数组
//float calin[20]={0.0005,0.001,0.002,0.004,0.008,0.016,0.032,0.064,0.128,0.256,0.512,1.024,2.048,4.096,8.192,16.384,32.768,65.536,131.072,262.144};//存放20位对应数值的数组
unsigned long cal[20]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288};//存放20位对应数值的数组
unsigned long calin[20]={5,10,20,40,80,160,320,640,1280,2560,5120,10240,20480,40960,81920,163840,327680,655360,1310720,2621440};//存放20位对应数值的数组

unsigned long xData,oData;//最终要输出的数据

int ledPin =  13;      // the number of the LED pin
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated
long interval = 500;           // interval at which to blink (milliseconds)

long previousGetMillis = 0;    //上次中断发生时间
long Timeout = 8;              //超时时间  8ms



void setup(){
  digitalWrite(dataIn, 1);
  digitalWrite( clockIn, 1);
  pinMode(dataIn, INPUT);                            //DATA line goes to Arduino digital pin 4
   pinMode(clockIn, INPUT);               
  Serial.begin(9600);
  delay(500);
  attachInterrupt(0,getBit,RISING);        //CLOCK line goes to Arduino digital pin 2 上升沿触发
  index =0;
   xData=0;
   oData=999;
}

void loop(){

  //超时处理
  if ((index !=0) && (millis() -  previousGetMillis > Timeout) ) {
     index=0;
     xData=0;
  };   
  //输出
  if (index >23) {
    if (oData !=xData) {
      if (isfs==1)
         Serial.print('-');
         
      if (isin==1){  //英寸
        Serial.print(xData/10000);
        Serial.print('.');
        if ((xData % 10000)<1000){  //补0

          if ((xData % 10000)<100){
             if ((xData % 10000)<10){
               Serial.print('0');
             };  
             Serial.print('0');
          };  
          Serial.print('0');
        };  
        Serial.println(xData % 10000);
      }else {   //公制
         
        Serial.print(xData/100);
        Serial.print('.');
        if ((xData % 100)<10)  //补0
          Serial.print('0');
        Serial.println(xData % 100);     
      };
    };  
    oData =xData;
    index=0;
    xData=0;
  };
  
  
   if (millis() - previousMillis > interval) {
      previousMillis = millis();   

      if (ledState == LOW)
         ledState = HIGH;
      else
         ledState = LOW;
      digitalWrite(ledPin, ledState);
  }
  
}



void getBit(){
  previousGetMillis=millis();
  if(index < 20){
    if(digitalRead(dataIn)==1){
        if (isin==0){
             xData =xData+cal[index];
        }else {
             xData =xData+calin[index];
        };         
    };
  } else {

    if (index==20)    //第21位为符号位
       isfs=digitalRead(dataIn);
            
   
     if (index==23)    //第24位为公英制 1=英制
       isin=digitalRead(dataIn);   
      
  };  

  index++;
}
17
发表于 2010-12-21 23:11 | 只看该作者
直接改个光光处理公制的吧,清晰多了:
///////////////////////////////////////////////////////////////////////////

//电子尺读数
//   gnd  data  clk  vcc1.5
// Pin Declarations
int dataIn = 3;
int clockIn = 2;


int index;
float cal[20]={0.01,0.02,0.04,0.08,0.16,0.32,0.64,1.28,2.56,5.12,10.24,20.48,40.96,81.92,163.84,327.68,655.36,1310.72,2621.44,5242.88};//存放20位对应数值的数组

float xData,oData;//最终要输出的数据

int ledPin =  13;      // the number of the LED pin
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated
long interval = 500;           // interval at which to blink (milliseconds)

long previousGetMillis = 0;    //上次中断发生时间
long Timeout = 8;              //超时时间  8ms



void setup(){
  digitalWrite(dataIn, 1);
  digitalWrite( clockIn, 1);
  pinMode(dataIn, INPUT);                            //DATA line goes to Arduino digital pin 4
   pinMode(clockIn, INPUT);               
  Serial.begin(9600);
  delay(500);
  attachInterrupt(0,getBit,RISING);        //CLOCK line goes to Arduino digital pin 2 上升沿触发
  index =0;
   xData=0;
   oData=999;
}

void loop(){

  //超时处理
  if ((index !=0) && (millis() -  previousGetMillis > Timeout) ) {
     index=0;
     xData=0;
  };   
  //串口输出
  if (index >23) {
    if (oData !=xData) {
        Serial.println(xData);     
     
    };  
    oData =xData;
    index=0;
    xData=0;
  };
  
   //运行状态灯闪烁处理
   if (millis() - previousMillis > interval) {
      previousMillis = millis();   

      if (ledState == LOW)
         ledState = HIGH;
      else
         ledState = LOW;
      digitalWrite(ledPin, ledState);
  }
  
}



void getBit(){
  previousGetMillis=millis();
  if(index < 20){
    if(digitalRead(dataIn)==1){
             xData =xData+cal[index];
        
    };
  } else {
    if (index==20)    //第21位为符号位
      if(digitalRead(dataIn)==1
          xData =0-xData;
      
  };  
  index++;
}

[ 本帖最后由 wxws 于 2010-12-21 23:14 编辑 ]
18
发表于 2010-12-21 23:13 | 只看该作者
顶个脚印。
19
发表于 2010-12-22 00:09 | 只看该作者
又顶多一个脚印
20
发表于 2010-12-22 00:14 | 只看该作者
唉 我傻啦
其实输出就直接是二进制 哪用什么换算哟
先低后高就OK了,最后除一下100.
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

关闭

【站内推荐】上一条 /1 下一条

快速回复 返回顶部 返回列表