模吧

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

楼主: 白小淘

DIY可控航灯控制器Version2(已发布所有硬件资料)

  [复制链接]
 楼主| 发表于 2016-9-23 09:44:15 | 显示全部楼层
sunybj 发表于 2016-9-23 09:02 DIY可控航灯控制器Version2(已发布所有硬件资料)  作者:白小淘 9025
aroudio有现成的代码吧?自己不打板就洞洞板加电阻三极管,买pro mimi 板

可以啊,代码我正在写。
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-9-23 22:48:27 | 显示全部楼层
本帖最后由 白小淘 于 2016-10-1 18:35 编辑
  1. 说好的今晚放新代码,实在太忙,先放出来,等过几天闲了再详细讲讲,这个代码貌似依旧有延时,现在用的计时器溢出中断。
复制代码

int mode=2;

void setup()
{
   DDRB = 0x0E;
   DDRD = 0xF8;   //置高D3-7,置低D0-2
   TCCR1A = 0;
   TCCR1B = 1<<CS11;
   bitSet(TIMSK1,TOIE1);
}

void loop()
{   
  switch(mode)
  {
    //以下是呼吸灯
    case(1):
      for(int t=0;t<=255;t=t+5)
      {
        analogWrite(3,t);
        analogWrite(5,t);
        analogWrite(6,t);
        analogWrite(9,t);
        analogWrite(10,t);
        analogWrite(11,t);
        delay(8);
      }
      delay(400);
      for(int t=255;t>=0;t=t-5)
      {
        analogWrite(3,t);
        analogWrite(5,t);
        analogWrite(6,t);
        analogWrite(9,t);
        analogWrite(10,t);
        analogWrite(11,t);
        delay(8);
      }
      delay(400);
    break;
    //以下是单闪
    case(2):
      PIND = 0xF8; PINB = 0x0E;
      delay(500);
    break;
    //以下是单闪一下,再连闪两下
    case(3):
      PIND = 0xF8; PINB = 0x0E;
      delay(160);  
      PIND = 0xF8; PINB = 0x0E;
      delay(550);
      PIND = 0xF8; PINB = 0x0E;
      delay(140);
      PIND = 0xF8; PINB = 0x0E;
      delay(100);
      PIND = 0xF8; PINB = 0x0E;
      delay(140);
      PIND = 0xF8; PINB = 0x0E;
      delay(600);
    break;

  }
}

ISR(TIMER1_OVF_vect)
{
  int a=pulseIn(2,1);
  //Serial.begin(9600);
  //Serial.println(a);   //串口查看信号用
  mode=2;
  if(a>1660){mode=3;}
  if(a<1330){mode=1;}
  return mode;
}

回复 支持 1 反对 0

使用道具 举报

发表于 2016-9-24 23:22:09 | 显示全部楼层
顶                              
回复 支持 1 反对 0

使用道具 举报

发表于 2016-9-25 18:13:36 | 显示全部楼层
延时试试这个代码,
void delayTime (uint16_t wait){
  end_time = millis() + wait ;
  while (millis() < end_time);
}  
然后为啥不用ws2812这类单总线的灯条。
回复 支持 0 反对 1

使用道具 举报

 楼主| 发表于 2016-9-25 18:19:32 | 显示全部楼层
zhaoyu3517 发表于 2016-9-25 18:13
延时试试这个代码,
void delayTime (uint16_t wait){
  end_time = millis() + wait ;

以后会考虑用WS2812的,我每个驱动旁边都有信号线,换ws2812应该只有电压需要考虑
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-9-26 21:59:31 | 显示全部楼层
本帖最后由 白小淘 于 2016-10-1 18:38 编辑

以下是这么多天没说话的成果,切换延时不大于22ms,人是感觉不到的。
这段程序是适用于三段开关(1模式呼吸,2模式单闪,3模式单闪一下,连闪两下),适用于两段开关(只有三段的1和3模式),也可以不用开关(只有呼吸)。
这段程序暂时还没有电压检测功能。后期加入电压检测后延时可能加大6-8ms,加入其他闪烁模式不会增加延时。
版权:本程序使用知识共享:署名-相同方式共享 协议发布,您可以自由的在任何地方使用该程序,(包括商业化也是被允许的,简单点说,拿去卖都可以)
          只需公开申明该程序为白小淘创作即可,如果您修改了该程序,必须申明以相同的方式共享才可以散布(不申明的只能自己用)。

int ZQ=4;
int mode;
extern volatile unsigned long timer0_millis;

void setup()
{
   DDRB = 0x0E;
   DDRD = 0xF8;   //置高D3-7,置低D0-2
   //TCCR1A = 0;
   //TCCR1B = 1<<CS11;
   //bitSet(TIMSK1,TOIE1);
}

void loop()
{   
  int a=pulseIn(2,1);
  if(a>1660){mode=3;}else{if(a<1330){mode=1;} else{mode=2;}}
  if(ZQ!=mode)
  {
    ZQ=mode;
    if(ZQ==1) {check3(0); check2(0); check1(1);}
    if(ZQ==2) {check1(0); check3(0); check2(1);}
    if(ZQ==3) {check1(0); check2(0); check3(1);}
  }
}

//ISR(TIMER1_OVF_vect){}

void check1(int i)
{
  if(i!=1) return;
  for(int t=0; t<=255; t=t+5)
      {
        analogWrite(3,t);
        analogWrite(5,t);
        analogWrite(6,t);
        analogWrite(9,t);
        analogWrite(10,t);
        analogWrite(11,t);
        delay(8);
      }
      int x=0; while(x <= 31){loop(); x++;}
      for(int t=255; t>=0; t=t-5)
      {
        analogWrite(3,t);
        analogWrite(5,t);
        analogWrite(6,t);
        analogWrite(9,t);
        analogWrite(10,t);
        analogWrite(11,t);
        delay(8);
      }
      x=0; while(x <= 31){loop(); x++;}
      check1(1);
}

void check2(int i)
{
  if(i!=1) return;
  PIND = 0xF8; PINB = 0x0E;
  int x=0; while(x <= 38){loop(); x++;}
  check2(1);
}

void check3(int i)
{
  if(i!=1) return;
  PIND = 0xF8; PINB = 0x0E;
  int x=0; while(x <= 13){loop(); x++;}
  PIND = 0xF8; PINB = 0x0E;
  x=0; while(x <= 43){loop(); x++;}
  PIND = 0xF8; PINB = 0x0E;
  x=0; while(x <= 11){loop(); x++;}
  PIND = 0xF8; PINB = 0x0E;
  x=0; while(x <= 8){loop(); x++;}
  PIND = 0xF8; PINB = 0x0E;
  x=0; while(x <= 11){loop(); x++;}
  PIND = 0xF8; PINB = 0x0E;
  x=0; while(x <= 48){loop(); x++;}
  check3(1);
}

回复 支持 2 反对 0

使用道具 举报

发表于 2016-9-26 22:33:25 | 显示全部楼层
看样子硬件还有很大的可以更改的余地啊
回复 支持 1 反对 0

使用道具 举报

发表于 2016-9-29 00:25:10 | 显示全部楼层
白小淘 发表于 2016-9-26 21:59
以下是这么多天没说话是成果,切换延时不大于22ms,人是感觉不到的。
这段程序是适用于三段开关(1模式呼吸 ...

懂的,感谢大神
回复 支持 1 反对 0

使用道具 举报

发表于 2016-9-29 07:26:16 | 显示全部楼层
帮顶!
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-10-5 23:46:11 | 显示全部楼层
本帖最后由 白小淘 于 2016-10-5 23:55 编辑

带有电压检测的全功能程序。
这个程序用了新的模式检测算法,节省了大约2ms左右的时间,然后加入的电压检测没有我想象中的耗时,所以,程序的模式切换延时在20ms内
程序从低压状态恢复正常状态的延时会大些,最大在460ms左右,但是这个……正常情况下电压是越来越低的吧……
一共2个模式,没有用3需要可以加上去,加上没有其他影响,1种模式呼吸,一种模式关闭。
任何状态下,电压低于10.8V灯开始单闪,低于10.5V开始常亮。
设计的理想状态下电压检测的误差在50mV以内,由于电阻误差的存在,实际误差会在100-200mV左右,这是使用的普通电阻,换高精会好得多。
检测电压的值,设计的是用实际电压除以0.05376得到的,下面的程序我校正过,所以除的0.0527。

int ZQ=4;         
int mode;
int val=0;

void setup()
{
   DDRB = 0x0E;
   DDRD = 0xF8;   
}

void loop()
{   
  mode=pulseIn(2,1);
  mode=mode/600;
  val=analogRead(0);
  if(val<200)  {m1(0); m2(0); m4(0); m3(1); return;}                    //电压低于10.5,开启模式3,关闭其他
  if(val<=205)  {m1(0); m3(0); m4(0); m2(1); return;}                //电压低于10.8,开启模式2,关闭其他
  if(ZQ!=mode)
  {
    ZQ=mode;
    if(ZQ==1) {m3(0); m2(0); m4(0); m1(1);}                    //这里没有了第2段,可控的模式只写了1,3两种,需要的可以加上去,没有影响
    if(ZQ==3) {m1(0); m2(0); m3(0); m4(1);}

  }
}


void m1(int i)
{

  if(i!=1) return;
  for(int t=0; t<=255; t=t+5)
      {
        analogWrite(3,t);
        analogWrite(5,t);
        analogWrite(6,t);
        analogWrite(9,t);
        analogWrite(10,t);
        analogWrite(11,t);
        delay(8);
      }
      int x=0; while(x <= 36){loop(); x++;}    //主循环运行一遍大约需要11ms,重复运行36遍,相当于延时396ms
      for(int t=255; t>=0; t=t-5)
      {
        analogWrite(3,t);
        analogWrite(5,t);
        analogWrite(6,t);
        analogWrite(9,t);
        analogWrite(10,t);
        analogWrite(11,t);
        delay(8);
      }
      x=0; while(x <= 36){loop(); x++;}
      m1(1);
}

void m2(int i) //模式2为单闪
{
  if(i!=1) return;
  PIND = 0xF8;
  PINB = 0x0E;
  ZQ=4;
  delay(450);
  loop();
  m2(1);
}

void m3(int i) //模式3为常亮所有通道
{
  if(i!=1) return;
  PORTB = 0x0E;
  PORTD = 0xF8;
  ZQ=4;
  delay(8);
  loop();
  m3(1);
}

void m4(int i) //模式4为关闭所有通道
{
  if(i!=1) return;
  PORTB = 0xF1; PORTD = 0x07;
  loop();
  m4(1);
}


评分

参与人数 1牛币 +10 收起 理由
nigesb942 + 10 很给力!

查看全部评分

回复 支持 2 反对 0

使用道具 举报

发表于 2016-10-11 08:31:44 | 显示全部楼层
报警电压设置的是不是有点低了?
回复 支持 0 反对 1

使用道具 举报

 楼主| 发表于 2016-10-11 09:38:04 来自手机 | 显示全部楼层
z小飞 发表于 2016-10-11 08:31
报警电压设置的是不是有点低了?

可以调的,我一般这样用,而且这个是两段报警,第一段就可以下来啊
回复 支持 0 反对 1

使用道具 举报

发表于 2016-10-12 08:30:56 | 显示全部楼层
路过,帮顶DIY可控航灯控制器Version2(已发布所有硬件资料)  作者:sjzzhsx 9825
回复 支持 0 反对 1

使用道具 举报

发表于 2016-10-12 15:16:21 | 显示全部楼层
路过,帮顶DIY可控航灯控制器Version2(已发布所有硬件资料)  作者:sjzzhsx 2131
回复 支持 0 反对 1

使用道具 举报

发表于 2016-11-2 07:27:01 | 显示全部楼层
噗,笑出声,你这么折腾是在显摆什么吗?用得着这么麻烦吗?最小系统mini328p只要搞定代码不就行了
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-11-13 13:30:29 | 显示全部楼层
还是讲一下Arduino烧写方法,和其他的有点不一样,导致刚接触的不容易理解。Atmel的单片机是不能直接用TTL写程序的,烧写使用的是ISP接口,但是Arduino IDE使用的却是TTL,原因在于事先已经往单片机里面写了bootloader。
正常情况下,bootloader只需要写一次,以后就都不用管了

bootloader上电后会第一个启动,之后负责和TTL通讯,将TTL的数据写到单片机的特定位置,并负责在上电时启动它们。大概就是这样子。

完整的过程:
焊接完成——使用ISP写入bootloader——使用串口写入程序。

ISP目前大都是免驱的了,也可以用,我用的ISP是开源的,所以,能在Arduino IDE里面直接写。IDE不支持的可以找卖家要配套的软件,一样的写。
另外,使用Arduino也可以写入示例里面的ArduinoISP之后使用。

使用Arduino的,把Arduino接上电脑,打开Arduino IDE,之后在【工具/Tools】-【开发板/board】菜单下选择对应的板子。
在【文件/File】-【示例/Examples】菜单下选择Arduino ISP。点击上传Upload按钮,显示上传成功后就可以了。

标准的写法:
把线连接好,一共6根,分别是VCC-VCC,GND-GND,SCK-SCK,MOSI-MOSI,MISO-MISO,RST-RST。这些ISP上面有写,硬件上面的26楼有图。、
ArduinoISP的也是6根,使用Arduino的第10脚接RST,这个在BL程序编程方法里面讲过。

接好后打开IDE,在【工具Tools】-【编程器/Programmer】菜单下依据你使用的编程器选择AVR ISP/USBASP/ArduinoISP 。
然后点击【工具/Tools】菜单下的“烧录引导程序/Burn Bootloader"就可以了。

免驱的似乎不支持上面的写法,那就要用Progisp了,这个软件,可以找卖家要配套的,不一定是这个名字,但是都拥有一样的功能和几乎一样的界面。
首先也是把线连好啦,然后点击Progisp上面的命令-读出识别字,看看连好了没有,如果没有问题的话,会在下面显示读出识别字成功,
读出成功后点击熔丝,写入需要的熔丝,再点击文件-调入Flash,调入Bootloader然后写入就好了
熔丝只动高位和低位,不要动其他的,Bootloader在Arduino安装目录下\hardware\arduino\avr\bootloaders,需要用哪个Bootloader和熔丝该写多少,也可以在Arduino的目录下根据你使用的单片机查,全部在这个文件里\hardware\arduino\avr\boards.txt
文件当然是全英文的,高位熔丝high_fuses=XXXX,低位熔丝low_fuses=XXXX,Bootlader文件位置bootloader.file=XXXXX

好像已经写完了引导,程序就很简单了
VCC GND TX RX和DTR,常见的几个线,接好后直接写就好了。就如同Arduino一样。
回复 支持 1 反对 0

使用道具 举报

发表于 2016-11-13 15:41:18 | 显示全部楼层
白小淘 发表于 2016-11-13 13:30
还是讲一下Arduino烧写方法,和其他的有点不一样,导致刚接触的不容易理解。Atmel的单片机是不能直接用TTL ...

亚麻跌,简单了点吧,懂的一看就懂,没搞过一看真看不懂
回复 支持 1 反对 0

使用道具 举报

发表于 2016-11-13 22:38:56 | 显示全部楼层
帮顶顶帮顶顶帮顶顶帮顶顶帮顶顶
回复 支持 1 反对 0

使用道具 举报

发表于 2016-11-14 09:15:08 | 显示全部楼层
顶顶顶顶顶顶顶顶
回复 支持 0 反对 1

使用道具 举报

发表于 2016-11-14 09:15:19 | 显示全部楼层
顶顶顶顶顶顶顶顶
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|关于模吧|APP下载|广告报价|小黑屋|手机版|企业会员|商城入驻|联系我们|模吧 ( 冀公网安备13080502000084号 )

© 2013-2020 Moz8.com 模吧,玩出精彩!