tyoo的KL25开源项目进行中[18B20单总线方式的多点测温系统]
本帖最后由 tyoo 于 2014-12-31 20:54 编辑项目描述:
基于18B20单总线方式的多点测温系统,下位机实现18B20温度数据读取,上位机实现实时显示、编号、历史数据等处理。该项目重点目标使用单总线方式通讯距离尽量达到500米,可挂的18B20数量尽量多,要求系统稳定。参与活动的目标暂设通讯距离150米(使用超五类网线),可挂18B20数量15只(每10米1个)。
硬件原理图:
明天补上
总费用:
序号 名称 规格 数量 单价 备注
1 网线 超五类,150米 0 0 已有
2 18B20 15 0 已有
3 打样 1 50+22 运费22
4 其它器件 1 10 部分已有,需要购买的不多
合计 82
计划完成时间:春节前
时间安排
1-1 完成硬件
1-2 开发环境搭建 XD你搞两个项目做什么? 单总线方式通讯距离尽量达到500米,这个有点难度! 单总线500米?是双绞线?屏蔽吗?
觉得是奇迹 holts2 发表于 2014-12-31 20:31
XD你搞两个项目做什么?
多谢提醒,网络故障了一下就成这样了,已修改另一个内容。 tyoo 发表于 2014-12-31 20:57
多谢提醒,网络故障了一下就成这样了,已修改另一个内容。
请版主删一个吧,不然分不清你用哪个 fengyunyu 发表于 2014-12-31 20:33
单总线方式通讯距离尽量达到500米,这个有点难度!
努力吧,官网一份手册中提到过。之前已经做过200米左右挂一只和3米挂20只的,没有系统化,稳定性也不太好,一直想完善却未行动。这次正好借这个机会,不再做行动的矮子。
下面是当初找的资料,还没有详细研究。
18B20总线没听过,这个能支持150M ? 试过这种总线的方式 和总线拓扑关系很大 以前做过类似的 用的是厂家的模块 数据稳定运行了两个多月 采集点大概60多个吧 单总线多点测温 ,挂这么多测温设备啊 子鱼 发表于 2014-12-31 22:19
以前做过类似的 用的是厂家的模块 数据稳定运行了两个多月 采集点大概60多个吧 ...
接了60个18B20测温 ? 等待楼主上图哈,,我好看看怎么个链接多个传感器,材料用什么比较好。。 子鱼 发表于 2014-12-31 22:19
以前做过类似的 用的是厂家的模块 数据稳定运行了两个多月 采集点大概60多个吧 ...
总线拓扑是怎么样的? fengyunyu 发表于 2015-1-1 15:36
总线拓扑是怎么样的?
需要保证每个端点到测试点的距离等长 星形连接 子鱼 发表于 2015-1-1 16:51
需要保证每个端点到测试点的距离等长 星形连接
这样太浪费线了 本帖最后由 tyoo 于 2015-1-1 21:02 编辑
单总线原理图:
由于KL25芯片不好买,方案改为KL25小板+驱动板的方式,上图是一个通道的单总线驱动,驱动板尺寸与KL25小板一致,驱动通道尽量多。
PDF中还有张RJ45x3的原理图,这张是网线每10米处的转接板。
-------------------------------------------------------------
补充版权声明:本项目同意授权发布在阿莫网站,阿莫网站和飞思卡尔拥有资料的发布权和使用权。 tyoo 发表于 2015-1-1 20:56
单总线原理图:
等待楼主上图哈。。 500米的距离,赞 Juggernaut 发表于 2015-1-2 10:33
500米的距离,赞
能传500米吗,真难相信 1-2 安装了KDS、KSDK。Elipse不陌生,试用还满意,有了KSDK也就不打算去深究KL25如何使用了。 系统板与上位机传输协议,参与活动先实现这些简单的功能。 这个距离感觉有难度,每次搞1-WIRE这个东西都搞得头大,期待楼主的作品。 tyoo 发表于 2015-1-1 20:56
单总线原理图:
和单片机是如何连接的?有完整的原理图么? DPU,SPU,DRIVE这些是什么 楼主我记得你用的这个传感器测温度其实不是很准 但是测量温度变化率是很准确的那么请问您是如何解决这个问题的呢 fengyunyu 发表于 2015-1-2 22:14
和单片机是如何连接的?有完整的原理图么?
DPU/SPU/DRIVE/SENSE这些信号直接与单片机IO连接,现在只画了单通道的,如果申请能通过,待KL25到手,根据板子引出的IO设计为多个通道的,这样也省的去买MCU,暂时也不用深究KL25原理图了。 luckner 发表于 2015-1-3 09:23
楼主我记得你用的这个传感器测温度其实不是很准 但是测量温度变化率是很准确的那么请问您是如何解决这 ...
没太明白,这次活动不考虑精度这些,能稳定、正确读取温度数据即可。
根据之前的使用情况来看,同一批的几十个同时使用时差别小于0.5℃(仅遇到过1只超过1℃),波动小于0.1℃。 feiante116 发表于 2015-1-2 22:40
DPU,SPU,DRIVE这些是什么
DPU:上拉
SPU:强上位(预留)
DRIVE:下拉 tyoo 发表于 2015-1-3 09:31
没太明白,这次活动不考虑精度这些,能稳定、正确读取温度数据即可。
根据之前的使用情况来看,同一批的 ...
我的意思是对的我之前也有做过实验 发现他们的温度变化率是相同的 顶起来{:smile:} 单总线的时序我在想还有没有更好的处理方式比如定时器 xianghaisha 发表于 2015-1-3 18:45
单总线的时序我在想还有没有更好的处理方式比如定时器
用中断方式节省资源 xianghaisha 发表于 2015-1-3 18:45
单总线的时序我在想还有没有更好的处理方式比如定时器
个人感觉还是用UART处理比较好,TX/RX接SENSE,数据收发均由硬件处理,不过单片机的UART数量有限,测温点较多时不适用。 tyoo 发表于 2015-1-3 20:28
个人感觉还是用UART处理比较好,TX/RX接SENSE,数据收发均由硬件处理,不过单片机的UART数量有限,测温点 ...
可以用软件模拟啊 holts2 发表于 2015-1-3 20:43
可以用软件模拟啊
使用UART的优势是不占用CPU即可读写温度传感器,用软件模拟出UART再用来读写温度传感器则与直接编写读写程序无本质区别 tyoo 发表于 2015-1-3 21:27
使用UART的优势是不占用CPU即可读写温度传感器,用软件模拟出UART再用来读写温度传感器则与直接编写读写 ...
不太明白18B20和MCU的通讯是用UART ? UART通讯可以150M ? holts2 发表于 2015-1-3 21:31
不太明白18B20和MCU的通讯是用UART ? UART通讯可以150M ?
1-wire总线是串行读写的,UART也是串行,调整好UART波特率,发送特定数据即可实现TX上输出控制18B20的时序 tyoo 发表于 2015-1-3 21:36
1-wire总线是串行读写的,UART也是串行,调整好UART波特率,发送特定数据即可实现TX上输出控制18B20的时 ...
还是没有整体的概念,待你弄得差不多我再来学习。 用uart的方式之前有一个网友提到过, 当时感觉想法真的很不错, 不过自己从来没试过.{:lol:} 没尝试过这么多这么远的 很看好楼主的创意设计 到时候回来学习下成功经验 很是期待这个大作啊。18B20在温度应用领域还是比较广泛的 tyoo 发表于 2015-1-3 21:36
1-wire总线是串行读写的,UART也是串行,调整好UART波特率,发送特定数据即可实现TX上输出控制18B20的时 ...
用UART控制18b20还是第一次听说,期待更多资料 好期待,感觉测试也是个大工程 本帖最后由 tyoo 于 2015-1-8 14:42 编辑
原计划做成KL25底板形式,实在等不到坛主审批就先做成单个形式。每个小板一个通道,为了省点打样费就自已拼板了。
PCB文件几次未能上传成功就放到云盘了
链接:http://pan.baidu.com/s/1bnzZGx5 密码:r60n
请大家帮忙看一下PCB有哪些需要修改,明天下班前下单打样。
另外,RJ45-TO92(双网口、18B20,每10米处转接板)做60个,1-WIRE Drive做了20个。前者我需要15个,后者需要1个,剩下的需要的网友请提前说,在下单时一并将器件配齐(需要代焊的说一声) 楼主,用串口方式还是模拟时序?mos管用的什么型号?? menghong_4 发表于 2015-1-7 19:31
楼主,用串口方式还是模拟时序?mos管用的什么型号??
对KL25不熟,软件还没开始,暂未确定用哪种方式驱动
这是选用的器件型号
2002年时用过DS18B20做过项目,总线上挂40个DS1820,总线长200米左右, 环境很不好,对传感器做了三防封装,用的是CD4050驱动,做过正向检测和反向仿真(为测试系统用CPU仿真40个传感器,可任意设置温度和报警及传感器故障模拟),原理图附上供参考, happyliu 发表于 2015-1-8 20:46
2002年时用过DS18B20做过项目,总线上挂40个DS1820,总线长200米左右, 环境很不好,对传感器做了三防封装 ...
程序方便贴出来学习一下吗 单总线方式通讯距离尽量达到500米 ,这个有点难吧 ! 彼岸花开@ 发表于 2015-1-1 07:42
等待楼主上图哈,,我好看看怎么个链接多个传感器,材料用什么比较好。。 ...
先做个单只的调试,网线已让工人做好,板子回来才发现RJ-45转TO-92那张板错了,图片中箭头所指是双RJ45,谁知实特两个竟是反的,引脚也是反的,板子用不了就按图中方法焊接一只先用着吧。
log:
1-15 套件已收到。软件开发环境也安装好了,昨晚把blink例程跑一下熟悉了软件使用。 学习~~~~~~~~~~~~~ 本打算趁年底两星期闲时把项目做完的,结果老板说这笔单结束没啥事了你就先放假回家吧{:cry:}{:cry:}{:cry:}{:cry:},所以今晚收拾收拾就回家了。网线不方便带回去,只好把板子带回去先调通单只的。
tyoo 发表于 2015-2-10 14:34
本打算趁年底两星期闲时把项目做完的,结果老板说这笔单结束没啥事了你就先放假回家吧{:cry: ...
这下有时间调了,搞定一只,也就搞定一篇 armok 发表于 2015-1-10 16:10
开发套件已经在前天寄出,申通:968804636479
运费我们已经支付,广东省内1-2天到,省外3-5天到。
年前可能完成不了,放到年后正月十五可以吗 tyoo 发表于 2015-2-11 07:42
年前可能完成不了,放到年后正月十五可以吗
应该 可以的,加紧调代码 楼主的这种线是哪里买的 拖了这么久还没完成,非常不好意思。
今天把串口与SHELL给整好了,很久没写代码有些手生,FREESCALE不熟再加上KDS用着很不爽,调试程序很是难受。下面先贴出SHELL和串口的主要代码(这些代码主要是参考网络修改整理的,在此感谢原作者):
/*
* shell.c
*
*Created on: 2015年3月2日
* Author:
*/
#include "shell.h"
#include "uart.h"
#include "string.h"
//命令缓存及标志
char gCmdBuf = {0};//增加一位结束符
uint_8 gCmdBufCnt = 0;//缓存计数
uint_8 gCmdBufStatus = 0; //0:接收中 1: 待处理 2:缓存满
int Cmd_help(int argc, char *argv[]);
tCmdLineEntry g_sCmdTable[] =
{
{ "help", Cmd_help, " : Display list of commands" },
{ "h", Cmd_help, " : alias for help" },
{ "?", Cmd_help, " : alias for help" },
{ 0, 0, 0 }
};
/*
* Cmd_help
*
*打印命令帮助信息
*/
int Cmd_help(int argc, char *argv[])
{
tCmdLineEntry *pEntry;
// Print some header text.
uart1_printf("\nAvailable commands\r\n");
uart1_printf("------------------\r\n");
// Point at the beginning of the command table.
pEntry = g_sCmdTable;
// Enter a loop to read each entry from the command table.The
// end of the table has been reached when the command name is NULL.
while(pEntry->pcCmd)
{
// Print the command name and the brief description.
uart1_printf("%s%s\r\n", pEntry->pcCmd, pEntry->pcHelp);
// Advance to the next entry in the table.
pEntry++;
}
//
// Return success.
//
return(0);
}
int CmdLineProcess(char *pcCmdLine)
{
static char *argv;
char *pcChar;
int argc;
int bFindArg = 1;
int re = 0;
tCmdLineEntry *pCmdEntry;
//
// Initialize the argument counter, and point to the beginning of the
// command line string.
//
argc = 0;
pcChar = pcCmdLine;
//
// Advance through the command line until a zero character is found.
//
while(*pcChar)
{
//
// If there is a space, then replace it with a zero, and set the flag
// to search for the next argument.
//
if(*pcChar == ' ')
{
*pcChar = 0;
bFindArg = 1;
}
//
// Otherwise it is not a space, so it must be a character that is part
// of an argument.
//
else
{
//
// If bFindArg is set, then that means we are looking for the start
// of the next argument.
//
if(bFindArg)
{
//
// As long as the maximum number of arguments has not been
// reached, then save the pointer to the start of this new arg
// in the argv array, and increment the count of args, argc.
//
if(argc < CMDLINE_MAX_ARGS)
{
argv = pcChar;
argc++;
bFindArg = 0;
}
//
// The maximum number of arguments has been reached so return
// the error.
//
else
{
return(CMDLINE_TOO_MANY_ARGS);
}
}
}
//
// Advance to the next character in the command line.
//
pcChar++;
}
//
// If one or more arguments was found, then process the command.
//
if(argc)
{
//
// Start at the beginning of the command table, to look for a matching
// command.
//
pCmdEntry = g_sCmdTable;
//
// Search through the command table until a null command string is
// found, which marks the end of the table.
//
while(pCmdEntry->pcCmd)
{
//
// If this command entry command string matches argv, then call
// the function for this command, passing the command line
// arguments.
//
if(!strcmp(argv, pCmdEntry->pcCmd))
{
re = pCmdEntry->pfnCmd(argc, argv);
uart1_printf("\r\n$");
}
//
// Not found, so advance to the next entry.
//
pCmdEntry++;
}
}
//
// Fall through to here means that no matching command was found, so return
// an error.
//
return(CMDLINE_BAD_CMD);
}
/*
* shell.h
*
*Created on: 2015年3月2日
* Author:
*/
#ifndef SHELL_H_
#define SHELL_H_
#include "common.h" //包含公共要素头文件
#include "sysinit.h"
#define CMD_BUF_SIZE 100
#define CMDLINE_MAX_ARGS 10
#define CMDLINE_BAD_CMD 1
#define CMDLINE_TOO_MANY_ARGS 2
typedef int (*pfnCmdLine)(int argc, char *argv[]);
//*****************************************************************************
//
//! Structure for an entry in the command list table.
//
//*****************************************************************************
typedef struct
{
//命令字符串
const char *pcCmd;
//命令实现函数
pfnCmdLine pfnCmd;
//命令帮助信息
const char *pcHelp;
}tCmdLineEntry;
extern char gCmdBuf;//增加一位结束符
extern uint_8 gCmdBufCnt;//缓存计数
extern uint_8 gCmdBufStatus; //0:接收中 1: 待处理 2:缓存满
extern int Cmd_help(int argc, char *argv[]);
extern int CmdLineProcess(char *pcCmdLine);
extern tCmdLineEntry g_sCmdTable[];
#endif /* SHELL_H_ */
串口苏大例程中加入了printf功能(不需要重定向的,稍加修改适用于任何开发环境哦):
void uart1_printf(char* fmt, ...)
{
double vargflt = 0;
intvargint = 0;
char* vargpch = NULL;
char vargch = 0;
char* pfmt = NULL;
va_list vp;
va_start(vp, fmt);
pfmt = fmt;
while(*pfmt)
{
if(*pfmt == '%')
{
switch(*(++pfmt))
{
case 'c':
vargch = va_arg(vp, int);
/* va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
printch(vargch);
break;
case 'd':
case 'i':
vargint = va_arg(vp, int);
printdec(vargint);
break;
case 'f':
vargflt = va_arg(vp, double);
/* va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI
mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */
printflt(vargflt);
break;
case 's':
vargpch = va_arg(vp, char*);
printstr(vargpch);
break;
case 'b':
case 'B':
vargint = va_arg(vp, int);
printbin(vargint);
break;
case 'x':
case 'X':
vargint = va_arg(vp, int);
printhex(vargint);
break;
case '%':
printch('%');
break;
default:
break;
}
pfmt++;
}
else
{
printch(*pfmt++);
}
}
va_end(vp);
}
void printch(char ch)
{
uart_send1(UART_1, ch);
}
void printdec(int dec)
{
if(dec==0)
{
return;
}
printdec(dec/10);
printch( (char)(dec%10 + '0'));
}
void printflt(double flt)
{
int tmpint = 0;
tmpint = (int)flt;
printdec(tmpint);
printch('.');
flt = flt - tmpint;
tmpint = (int)(flt * 1000000);
printdec(tmpint);
}
void printstr(char* str)
{
while(*str)
{
printch(*str++);
}
}
void printbin(int bin)
{
if(bin == 0)
{
printstr("0b");
return;
}
printbin(bin/2);
printch( (char)(bin%2 + '0'));
}
void printhex(int hex)
{
if(hex==0)
{
printstr("0x");
return;
}
printhex(hex/16);
if(hex < 10)
{
printch((char)(hex%16 + '0'));
}
else
{
printch((char)(hex%16 - 10 + 'a' ));
}
}
串口中断接收程序
//串口1接收中断服务例程
void isr_uart1_re(void)
{
uint_8 ch;
uint_8 flag = 1;
DISABLE_INTERRUPTS;
ch = uart_re1(UART_1, &flag);
if (0 == flag)
{
uart_send1(UART_1, ch);
if (ch != '\r')
{
if (gCmdBufStatus == 0)
{
gCmdBuf = ch;
if (gCmdBufCnt == CMD_BUF_SIZE)
gCmdBufStatus = 2;
}
}
else
{
uart_send1(UART_1, '\n');
gCmdBuf = '\0';
gCmdBufCnt = 0;
gCmdBufStatus = 1;
}
}
ENABLE_INTERRUPTS;
}
程序主循环中加入下面内容即可处理命令:
if (gCmdBufStatus == 1)
{
CmdLineProcess(gCmdBuf);
gCmdBufStatus = 0;
} 以前做过类似应用,挂128只18B20确实可以到几百米的通讯距离。不过做稳定还是需要下一番功夫的。
1、接口驱动电路设计很关键
2、软件时序需要精准 XD项目完成了吗 ? 500米那么远,感觉很不可思议!成功了吗?楼主 jiang887786 发表于 2015-3-7 09:45
500米那么远,感觉很不可思议!成功了吗?楼主
加上转接放大器,还可以远 holts2 发表于 2015-3-7 10:02
加上转接放大器,还可以远
太远的话,波形时序都会很难掌握吧?再加上元器件的环境温度变化等等外界因素。我感觉太远了还是不靠谱。 superrf 发表于 2015-1-4 12:55
用UART控制18b20还是第一次听说,期待更多资料
同求相关资料,我以前写过单总线程序,还是非常要求时间精准的,UART是怎么完成的呢? 太慢!{:dizzy:} 也玩过18B20单总线的,500米的距离LZ成功没? 期待楼主大作 embeddev_1 发表于 2015-3-7 16:11
太慢!
对不住大家了,能力不足,现在很少敲代码,对飞思卡尔的也不熟偏偏又选择了KDS来开发,再加上工作、家庭的各种烦琐小事,最关键还有本人的毅力不够坚强,所以一慢再慢,不过相信自己还是能坚持做完的,即使做那只最慢的蜗牛也要将自己的兴趣进行到底。
PS:不做研发后的写代码状态很不好{:mad:} 。 tyoo 发表于 2015-3-10 16:36
对不住大家了,能力不足,现在很少敲代码,对飞思卡尔的也不熟偏偏又选择了KDS来开发,再加上工作、家庭 ...
如果你原来做过,只是移植应该问题 不大的 holts2 发表于 2015-3-10 18:19
如果你原来做过,只是移植应该问题 不大的
这次驱动方法、搜索方法、驱动电路都是新方式 mq-life 发表于 2015-3-10 19:37
这次驱动方法、搜索方法、驱动电路都是新方式
只是传送远点,其它没区别吧 楼主,一个月了。做的怎么样了? menghong_4 发表于 2015-4-8 13:39
楼主,一个月了。做的怎么样了?
别提了,现在每天四点就得起床忙活,两份工作真不好做,累死了,这玩意好久没碰了 tyoo 发表于 2015-4-29 08:56
别提了,现在每天四点就得起床忙活,两份工作真不好做,累死了,这玩意好久没碰了 ...
加油啊,善始善终,好歹得把交的钱拿回来吧 ? 如果成本可以稍微提高点的话,我建议使用485总线传输,毕竟差分信号传输比起普通的TTL传输要好些~ 不错啊 谢谢楼主分享! tyoo 发表于 2014-12-31 21:15
努力吧,官网一份手册中提到过。之前已经做过200米左右挂一只和3米挂20只的,没有系统化,稳定性也不太好 ...
楼主怎么不可以下载啊
怎么没有后续呢
页:
[1]