首页 » 通讯 » 梦幻 LED 感应餐桌妹纸的最爱屌丝 的契机!_传感器_插座

梦幻 LED 感应餐桌妹纸的最爱屌丝 的契机!_传感器_插座

乖囧猫 2025-01-15 20:42:09 0

扫一扫用手机浏览

文章目录 [+]

这是一款利用了红外靠近传感器的小桌子,加上 LED 的光照效果,犹如互

动式的梦幻餐桌。

梦幻 LED 感应餐桌妹纸的最爱屌丝  的契机!_传感器_插座 梦幻 LED 感应餐桌妹纸的最爱屌丝  的契机!_传感器_插座 通讯

这个项目包含了三个 8x8 独立的模块,每个模块包含 4 个“光点”,每个光点

梦幻 LED 感应餐桌妹纸的最爱屌丝  的契机!_传感器_插座 梦幻 LED 感应餐桌妹纸的最爱屌丝  的契机!_传感器_插座 通讯
(图片来自网络侵删)

由 21 个 LED、2 个红外发射二极管以及 2 个红外光电二极管组成。

第 1 1 步 材料准备

元器件列表如下,格式为:

型号(Part number)

厂商

描述

556-ATMEGA48-20PU

Atmel 微掌握器(MCU)

4kB Flash 0.256kB

638-IR204-A

Everlight 红外发射管

红外 LED 940nm

512-QSD2030F

Fairchild 光电二极管

光电二极管

757-ULN2803APG(5,M)

Toshiba 达林顿晶体管

8CH. 50V/.5A IFD IC

595-TLC274CN

TI Op Amps

Quad LiMCMOS

511-L7805CV

ST 标准线性调节器

5.0V 1.0A Positive

571-1-390261-3

Tyco IC 插座

14P ECONOMY TIN

571-1-390261-5

Tyco IC 插座

18P ECONOMY TIN

571-1-390261-9

Tyco IC 插座

28P ECONOMY TIN SKT

第 2 2 步 制作红外传感器

我所采取的传感器因此逆向偏压形式并联的 IR 光电二极管,形成一个大略

的分压电路。
当光电二极管逆向连接时(就像 LED 倒接一样),就可以随着光

线(紧张是红外光)的强弱改变电阻值。

V-in 是 5V。

第 3 3 步 红外发射管

我用的是 3mm 红外 LED。
为了得到更大的感应范围,IR 发射管要非常亮,

以是须要大电流。

我把 IR 发射管连接到达林顿芯片上,这样在开或关时掌握器可以被触发。

由于 ADC 转换切换得很快,以是先打开 IR 发射管,等 IR 传感器设置好后,让

ADC 进行读数,然后关闭。

定时器 1 从 0 数到 65535。
而 8MHz 的 fCPU 使掌握器在 8.2 毫秒内从 0 数

到 65535。
这样每 8.2 毫秒发生一次 IR 感应序列。

每一束光里面的两个 IR 发射管之间串联起来,电源电压是 5V。

波形图如上图所示。

第 4 4 步 编写代码

代码见附件

001 /

002 PIN ASSIGNMENTS ON ATMEGA48

003

004 PC6 (PCINT14/RESET)

005 PC5 (ADC5/SCL/PCINT13) // I2C 时钟输入

006 PC4 (ADC4/SDA/PCINT12) // I2C 数据输入

007 PC3 (ADC3/PCINT11) //传感器 4 IR 吸收器

008 PC2 (ADC2/PCINT10)

009 PC1 (ADC1/PCINT9)

010 PC0 (ADC0/PCINT8)

011

012 PB7 (PCINT7/XTAL2/TOSC2) //IR 4 触发

013 PB6 (PCINT6/XTAL1/TOSC1) //IR 3 触发

014 PB5 (SCK/PCINT5)

015 PB4 (MISO/PCINT4)

016 PB3 (MOSI/OC2A/PCINT3) //PWM 3

017 PB2 (SS/OC1B/PCINT2)

018 PB1 (OC1A/PCINT1)

019 PB0 (PCINT0/CLKO/ICP1)

020

021 PD0 (PCINT16/RXD)

022 PD1 (PCINT17/TXD)

023 PD2 (PCINT18/INT0)

024 PD3 (PCINT19/OC2B/INT1) //PWM 4

025 PD4 (PCINT20/XCK/T0)

026 PD5 (PCINT21/OC0B/T1) //PWM 2

027 PD6 (PCINT22/OC0A/AIN0) //PWM 1

028 PD7 (PCINT23/AIN1)

029 /

030

031 #define IR_1_ON PORTB |= (1<<4)

032 #define IR_2_ON PORTB |= (1<<5)

033 #define IR_3_ON PORTB |= (1<<6)

034 #define IR_4_ON PORTB |= (1<<7)

035 #define IR_1_OFF PORTB &= ~(1<<4)

036 #define IR_2_OFF PORTB &= ~(1<<5)

037 #define IR_3_OFF PORTB &= ~(1<<6)

038 #define IR_4_OFF PORTB &= ~(1<<7)

039

040 #define PWM1 6 //PORTD PWM 引脚分配

041 #define PWM2 5 //PORTD

042 #define PWM3 3 //PORTB

043 #define PWM4 3 //PORTD

044

045 #define F_CPU 8000000UL

046

047 #include

048 #include

049 #include

050 //#include

051

052 /Function Declarations/

053 int ADC_read(void);

054 void A2D_Channel_Select(unsigned char channel);

055 void Init_ADC(void);

056 void Init_Timer0(void);

057 void Init_Timer1(void);

058 void Init_Timer2(void);

059 void Delay(void);

060 void Calibrate_Sensors(void);

061 //void Init_I2C_Slave_Rx(void);

062

063

064 /Global Variable Declarations/

065 volatile char Sensor_Values_Updated = 0;

066 volatile char Timer1_Overflow = 0;

067 volatile unsigned char channel = 0;

068

volatile int Amb_Sensor_1 = 0, Amb_Sensor_2 = 0, Amb_Sensor_3 = 0,

Amb_Sensor_4 = 0;

069 volatile int Sensor_1 = 0, Sensor_2 = 0, Sensor_3 = 0, Sensor_4 = 0;

070

volatile int Initial_1 = 0, Initial_2 = 0, Initial_3 = 0, Initial_4

= 0;

071

volatile int New_PWM1 = 0, New_PWM2 = 0, New_PWM3 = 0, New_PWM4 =

0;

072 volatile int Old_PWM1 = 0, Old_PWM2 = 0, Old_PWM3 = 0, Old_PWM4 = 0;

073

074 unsigned char buffer = 8;

075

076 int main(void)

077 {

078 DDRB = 0xff;

079 //make sure IR emitters are turned off, and PWM 3

080

PORTB &= ~((1 << 7)|(1 << 6)|(1 << 5)|(1 << 4)|(1 <<

3));

081 DDRC = 0x00;

082

083 DDRD = 0xff;

084 PORTD = 0x00; //使所有 PORT D 为低

085

086 Init_ADC();

087

088 sei();

089

090 Calibrate_Sensors();

091

092 PORTD |= (1 << PWM1);

093 _delay_ms(600);

094 PORTD &= ~(1 << PWM1);

095

096 Init_Timer0();

097 Init_Timer2();

098

099 //Init_I2C_Slave_Rx();

100

101 while(1)

102 {

103 //do something?

104 //. . .

105 }

106

107 }

108

109

110 ISR(TIMER1_OVF_vect)

111 {

112 Timer1_Overflow++;

113 switch(Timer1_Overflow)

114 {

115 case 1:

11

6

A2D_Channel_Select(0);

//select ADC channel 0

117 Amb_Sensor_1 = ADC_read();

11

8

IR_1_ON;

//turn on IR 1 LED, PORTB |= (1<<4)

11

9

Delay();

//delay for the IR receiver to settle

120

Sensor_1 =

ADC_read(); //take active ADC reading of

IR receiver

12

1

IR_1_OFF;

//turn off IR 1 LED

122

123

New_PWM1 = (Sensor_1 - Amb_Sensor_1) -

Initial_1; //condition readings

124

if(New_PWM1 <= 0) { New_PWM1 =

0; }

125

New_PWM1 = ((7Old_PWM1)>>3) +

(New_PWM1>>3);

126

127 if(OCR0A >= 1) {DDRD |= (1 << PWM1);}

128

else { DDRD &= ~(1 <<

PWM1); } New_PWM1 <<=

2;

129 if(New_PWM1 > 255) { New_PWM1 = 255; }

130 OCR0A = New_PWM1;

131 New_PWM1 >>= 2;

132

133

134 / //Trigger sequence

135 if(New_PWM1 > Initial_1)

136 {

137 DDRD |= (1 << PWM1);

138

139 if(OCR0A < 255)

140 {

141 OCR0A += (255 - OCR0A)>>2 ;

142 //OCR0A++;

143 }

144

145 if (New_PWM1 < (Initial_1 + 8))

146 {

147

Initial_1 = ((7Initial_1)>>3)

+ (New_PWM1>>3);

148 }

149 }

150

151 else if(New_PWM1 < Initial_1)

152 {

153 if(OCR0A > 0)

154 {

155 OCR0A -= (OCR0A >> 4)+1;

156 //OCR0A--;

157 }

158 else if(OCR0A <= 0)

159 {

160 DDRD &= ~(1 << PWM1);

161 }

162 }

163 /

164 Old_PWM1 = New_PWM1;

165 break;

166

167 case 2:

16

8

A2D_Channel_Select(1);

//select ADC channel 1

169 Amb_Sensor_2 = ADC_read();

17

0

IR_2_ON;

//turn on IR 2 LED, PORTB |= (1<<5)

17

1

Delay();

//delay for the IR receiver to settle

172 Sensor_2 =

ADC_read(); //take ADC reading

17

3

IR_2_OFF;

//turn off IR 2 LED

174

175

New_PWM2 = (Sensor_2 - Amb_Sensor_2) -

Initial_2;

176 if(New_PWM2 < 0) { New_PWM2 = 0; }

177

178 New_PWM2 = ((7Old_PWM2)>>3) + (New_PWM2>>3);

179 if(OCR0B >= 1) {DDRD |= (1 << PWM2);}

180 else { DDRD &= ~(1 << PWM2); }

181

182 New_PWM2 <<= 2;

183 if(New_PWM2 > 255) { New_PWM2 = 255; }

184 OCR0B = New_PWM2;

185 New_PWM2 >>= 2;

186 /

187 if(New_PWM2 > Initial_2)

188 {

189 DDRD |= (1 << PWM2);

190

191 if(OCR0B < 255)

192 {

193 OCR0B += (255 - OCR0B)>>2 ;

194 //OCR0B++;

195 }

196

197 if (New_PWM2 < (Initial_2 + 8))

198 {

199

Initial_2 = ((7Initial_2)>>3)

+ (New_PWM2>>3);

200 }

201 }

202

203 else if(New_PWM2 < Initial_2)

204 {

205 if(OCR0B > 0)

206 {

207 OCR0B -= (OCR0B >> 4)+1;

208 //OCR0B--;

209 }

210 else if(OCR0B <= 0)

211 {

212 DDRD &= ~(1 << PWM2);

213 }

214 }

215 /

216 Old_PWM2 = New_PWM2;

217 break;

218

219 case 3:

22

0

A2D_Channel_Select(2);

//select ADC channel 2

221 Amb_Sensor_3 = ADC_read();

22

2

IR_3_ON;

//turn on IR 3 LED, PORTB |= (1<<6)

22

3

Delay();

//delay for the IR receiver to settle

224

Sensor_3 =

ADC_read(); //take ADC reading

22

5

IR_3_OFF;

//turn off IR 3 LED

226

227

New_PWM3 = (Sensor_3 - Amb_Sensor_3) -

Initial_3;

228 if(New_PWM3 < 0) { New_PWM3 = 0; }

229

230 New_PWM3 = ((7Old_PWM3)>>3) + (New_PWM3>>3);

231 if(OCR2A >= 1) {DDRB |= (1 << PWM3);}

232 else { DDRB &= ~(1 << PWM3); }

233 New_PWM3 <<= 2;

234 if(New_PWM3 > 255) { New_PWM3 = 255; }

235 OCR2A = New_PWM3;

236 New_PWM3 >>= 2;

237 /

238 if(New_PWM3 > Initial_3)

239 {

240 DDRB |= (1 << PWM3);

241

242 if(OCR2A < 255)

243 {

244 OCR2A += (255 - OCR2A)>>2 ;

245 //OCR2A++;

246 }

247

248 if (New_PWM3 < (Initial_3 + 8))

249 {

250

Initial_3 = ((7Initial_3)>>3)

+ (New_PWM3>>3);

251 }

252 }

253

254 else if(New_PWM3 < Initial_3)

255 {

256 if(OCR2A > 0)

257 {

258 OCR2A -= (OCR2A >> 4)+1;

259 //OCR2A--;

260 }

261 else if(OCR2A <= 0)

262 {

263 DDRB &= ~(1 << PWM3);

264 }

265 }

266 /

267 Old_PWM3 = New_PWM3;

268 break;

269

270 case 4:

27

1

A2D_Channel_Select(3);

//select ADC channel 3

272 Amb_Sensor_4 = ADC_read();

27

3

IR_4_ON;

//turn on IR 4 LED, PORTB |= (1<<7)

27

4

Delay();

//delay for the IR receiver to settle

275

Sensor_4 =

ADC_read(); //take ADC reading

27

6

IR_4_OFF;

//turn off IR 4 LED

277

278

New_PWM4 = (Sensor_4 - Amb_Sensor_4) -

Initial_4;

279 if(New_PWM4 < 0) { New_PWM4 = 0; }

280

281 New_PWM4 = ((7Old_PWM4)>>3) + (New_PWM4>>3);

282 if(OCR2B >= 1) {DDRD |= (1 << PWM4);}

283 else { DDRD &= ~(1 << PWM4); }

284 New_PWM4 <<= 2;

285 if(New_PWM4 > 255) { New_PWM4 = 255; }

286 OCR2B = New_PWM4;

287 New_PWM4 >>= 2;

288 /

289 if(New_PWM4 > Initial_4)

290 {

291 DDRD |= (1 << PWM4);

292

293 if(OCR2B < 255)

294 {

295 OCR2B += (255 - OCR2B)>>2 ;

296 //OCR2B++;

297 }

298

299 if (New_PWM4 < (Initial_4 + 8))

300 {

301

Initial_4 = ((7Initial_4)>>3)

+ (New_PWM4>>3);

302 }

303 }

304

305 else if(New_PWM1 < Initial_4)

306 {

307 if(OCR2B > 0)

308 {

309 OCR2B -= (OCR2B >> 4)+1;

310 //OCR2B--;

311 }

312 else if(OCR2B <= 0)

313 {

314 DDRD &= ~(1 << PWM4);

315 }

316 }

317 /

318 Old_PWM4 = New_PWM4;

319

320

Timer1_Overflow =

0;

321 Sensor_Values_Updated = 1;

322

323 break;

324 }//end switch

325 }//end ISR

326

327

328 /

329 ISR(TWI_vect) //to include later when I get this figured

out

330 {

331 switch(TWSR)

332 {

333

case TW_SR_SLA_ACK: //0x60 //Own

address Rx

334 Byte_Number == 1;

335 break;

336

337

case TW_SR_DATA_ACK: // 0x80 , data in

TWDR

338 switch(Byte_Number)

339 {

340 case 1:

341 Reg_Addr = TWDR;

342 Byte_Number++;

343 break;

344

345 case 2:

346 Reg_Val = TWDR;

347

Byte_Number = 0; //reset, unless

more bytes are coming

348 break;

349

350 case Max_Bytes_Expected:

351 Reg_Val = TWDR;

352

Byte_Number = 0; //reset, unless

more bytes are coming

353 break;

354 }

355 break;

356

357 case TW_SR_GCALL_DATA_ACK: // 0x90

358 if(Byte_Number == 1)

359 {

360 Reg_Addr = TWDR;

361 Byte_Number++;

362 }

363 else if(Byte_Number == 2)

364 {

365 Reg_Val = TWDR;

366

Byte_Number = 0; //reset, unless

more bytes are coming

367 }

368 break;

369 }//end switch

370 }//end ISR

371

372

373 void Init_I2C_Slave_Rx(void)

374 {

375 //Set Device Address in TWAR

376 TWAR = 10;

377

378 TWCR |= ((1 << TWEA)|(1 << TWEN));

379 TWCR &= ~((1 << TWSTA)|(1 << TWSTO));

380 }

381 /

382

383

384

void Calibrate_Sensors(void) //establish initial ambient sensor

values

385 {

386 char q = 0;

387

388 Init_Timer1();

389

390 for(q=0; q<32; q++) //should take one second-ish

391 {

392 //wait for Sensor cycle to be done, then gather

sensors values

393 while(Sensor_Values_Updated == 0) {}

394

395

Initial_1 += (Sensor_1 -

Amb_Sensor_1); //initial difference

396 Initial_2 += (Sensor_2 - Amb_Sensor_2);

397 Initial_3 += (Sensor_3 - Amb_Sensor_3);

398 Initial_4 += (Sensor_4 - Amb_Sensor_4);

399

400 Sensor_Values_Updated = 0; //reset

401 }

402

403 //condition Initial Ambient Sensor values, plus a buffer

404 Initial_1 = (Initial_1 >> 5) + buffer;

405 Initial_2 = (Initial_2 >> 5) + buffer;

406 Initial_3 = (Initial_3 >> 5) + buffer;

407 Initial_4 = (Initial_4 >> 5) + buffer;

408 }

409

410 void Init_ADC(void)

411 {

412

ADMUX |= 1 << REFS0; //AVCC with external

capacitor at AREF pin

413 ADMUX |= (1<

414 }

415

416 void Init_Timer0(void)

417 {

418

//Fast PWM, non-inverting, WGM02-WGM00 == 011, no overflow

interrupt

419

TCCR0A |= ((1 << COM0A1)|(1 << COM0B1)|(1 << WGM01)|(1 <<

WGM00));

420 TCCR0B |= (1 << CS00); //start clock, no prescale

421 }

422

423 void Init_Timer1(void)

424 {

425 //no PWM, enable overflow interrupt,

426

//TOP == 0xFFFF == 65536 cycles == roughly 122 overflow

interrupts/sec

427 TCCR1B |= (1 << CS10);

428 TIMSK1 |= (1 << TOIE1);

429 }

430

431

void Init_Timer2(void) //PWM for sensors

3 & 4

432 {

433

//Fast PWM, non-inverting, WGM22-WGM20 == 011, no overflow

interrupt

434

TCCR2A |= ((1 << COM2A1)|(1 << COM2B1)|(1 << WGM21)|(1 <<

WGM20));

435 TCCR2B |= (1 << CS20); //start clock, no prescale

436 }

437

438

439

int ADC_read(void) /select ADC channel

prior to calling this function/

440 {

441 int ADC_value = 0;

442 int ADCsample;

443 char i;

444

445

ADCSRA |= (1< ADCSRA |= (1< while ((ADCSRA

& ADSC));

446

447 for (i=0; i<64; i++)

448 {

449

ADCSRA |= (1< while ((ADCSRA &

ADSC)); //wait for conversion to finish

450

//change back to ADCL for 10 bit precision, and remove left-shift bit

setting

451 ADCsample = ADCH;

452 //ADCsample += (ADCH<<8);

453

ADC_value += ADCsample; //add ADCsample

to ADC_sensor

454 }

455

456

457 return ADC_value;

458

459 ADCSRA &= ~(1<

460 void A2D_Channel_Select(unsigned char channel)

461 {

462

463 switch (channel)

464 {

465 case 0:

466 ADMUX &= ~((1 << 3)|(1 << 2)|(1 << 1)|(1 << 0));

467 break;

468

469 case 1:

470 ADMUX &= ~((1 << 3)|(1 << 2)|(1 << 1));

471 ADMUX |= (1 << 0);

472 break;

473

474 case 2:

475 ADMUX &= ~((1 << 3)|(1 << 2)|(1 << 0));

476 ADMUX |= (1 << 1);

477 break;

478

479 case 3:

480 ADMUX &= ~((1 << 3)|(1 << 2));

481 ADMUX |= ((1 << 1)|(1 << 0));

482 break;

483 / I am not using these for this project

484 case 4:

485 ADMUX &= ~((1 << 3)|(1 << 1)|(1 << 0));

486 ADMUX |= (1 << 2);

487 break;

488

489 case 5:

490 ADMUX &= ~((1 << 3)|(1 << 1));

491 ADMUX |= ((1 << 2)|(1 << 0));

492 break;

493 /

494 }//end switch

495 }

496

497 void Delay(void)

498 {

499 _delay_us(100);

500 }

第 5 5 步 电路

电路图和制成后的电路板如下图。

标签:

相关文章