Guest User

Untitled

a guest
Jul 22nd, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.75 KB | None | 0 0
  1. /*********************************************************
  2. 2313dmx_hzsync_com_test_001: DMX HzSynchronize Common test ver0.2
  3.  
  4. for ATtiny2313 (8MHz)
  5. at PCB :dmx-rec2313s ver2.0 late
  6. ただしダイオードをジャンパーに置き換え
  7. 入出力にプルダウン追加必要
  8.  
  9. main.c
  10.  
  11. DMX512 4ch DIMMER
  12. DMX channel (base address + n)
  13. 0ch: (PWM0:PD5)ACPumpTriac
  14. 1ch: (PWM1:PB3,PB4)25kHzPWMcontrolFAN
  15.  
  16. DMX base address
  17. Address 256 128 64 32 16 8 4 2 1
  18. i-bit 8 7 6 5 4 3 2 1 0
  19. PORT PB7 PB6 PB5 PB1 PB0 PD6 PD4 PD3 PD2
  20. (address=0 =>512ch)
  21.  
  22. 8MHz=0.000125ms=0.125µs
  23.  
  24. PB2:ACゼロクロストリガー入力:0.5ms=500µs
  25. PD5:AC非ゼロクロストリガー出力
  26. PB3:二重反転ファン吸込側PWM(茶)25kHz:PB4と同期
  27. PB4:二重反転ファン吐出側PWM(白)25kHz:PB3と同期
  28.  
  29. PD1:PD1PullUp(H:共通/L:50Hz限定)
  30.  
  31. #HighFuse 0xdf = 0b11011111
  32. #LowFuse 0xfc = 0b11111100
  33.  
  34. v0.1 20180721 "2313dmx_hzsync_test_001"より分岐
  35. PD1High(PullUp),スイッチを省いた時に周波数共通設定
  36. その場合,50Hz約40~75%,60Hz約10~50%の制御となる
  37. ただし液送りのため,双方Full動作追加
  38. 目的上,ポンプを7割以上稼働しない前提
  39.  
  40.  
  41. Created by Tsunehiro Oketani
  42. Copyright oketronics 2018 All rights reserved.
  43. *********************************************************/
  44.  
  45. #include <avr/io.h>
  46. #include "dmx_recv.h"
  47.  
  48. #define DMX_SIZE 2 //連続するDMX受信チャンネル数
  49. //"dmx_recv.h"のDMX_BUF_SIZEが上限
  50.  
  51. static volatile int a; //a:ゼロクロス検出フラグ
  52. //staticは記述されたファイル内でのみ使用が制限される変数,0に初期化される
  53. //volatileは常に更新される変数,最適化による消失防止
  54.  
  55. /**ゼロクロス検出**/
  56. //AC100Vのゼロクロスを検出しPB2にHigh入力
  57. //優先順位がUSARTRX割込みより低いピン変化割込み
  58. ISR(PCINT_vect){
  59. if(!a){ //a == 0,次のゼロクロス入力待機
  60. if(PINB & _BV(PINB2)){ //PB2にゼロクロスHigh入力があったら
  61. //TCNT0 = 0; //Timer0カウントをリセット
  62. a=1; //検出中
  63. }
  64. }
  65.  
  66. if(a){ //a == 1,ゼロクロス検出中
  67. //Timer0スタート時(PD5出力時)に確実に0Vを超えているように
  68. //ゼロクロスをフォトトライアックが検出中はTimer0を停止しておく
  69. if(PINB & _BV(PINB2)){
  70. TCNT0 = 0; //Timer0カウントをリセット
  71. //a = 1;
  72. }
  73. //else {a = 0;}
  74. }
  75.  
  76. if(!(PINB & _BV(PINB2))){
  77. a = 0;
  78. }
  79.  
  80. }
  81.  
  82.  
  83. /**PWM出力のための設定と初期化**/
  84. void init_pwm (void) {
  85.  
  86. /*8bit高速PWM(ACポンプ制御フォトトライアック)*/
  87. //Timer0カウンター、比較レジスタを初期化
  88. TCNT0 = 0;
  89. OCR0A = 0;
  90. OCR0B = 0;
  91.  
  92. //高速PWM動作,TOP値COR0A
  93. TCCR0B |= _BV(WGM02);
  94. TCCR0A |= _BV(WGM01) | _BV(WGM00);
  95.  
  96. //比較一致でHigh、BOTTOMでLowをOC0Bへ出力(反転動作)
  97. TCCR0A |= _BV(COM1B0) | _BV(COM1B1);
  98.  
  99. ////Timer0:AC50Hzおよび60Hz同期////
  100. //クロック周波数/(タイマー分周*TOP値COR0A)=AC半波
  101.  
  102. //PD1High(PullUp):50,60Hz共通設定
  103. //8,000,000 / (256 * COR0A) = (60 x 2)の近似値
  104. if(PIND & _BV(PIND1)){ //PD1がHighであれば
  105. TCCR0B |= _BV(CS02); //8MHz/256分周=31250Hz
  106. OCR0A = 0xf0; //240:0xf0:130.2Hz
  107. }
  108. //PD1Low:東日本50Hz限定最適化
  109. //8,000,000 / (1024 * COR0A) = (50 x 2)の近似値
  110. if(!(PIND & _BV(PIND1))){//PD1がLowであれば
  111. TCCR0B |= _BV(CS02) | _BV(CS00);//8MHz/1024分周=7812.5Hz
  112. OCR0A = 0x4d; //東日本50HzのOCR0A値(77=78-1:0x4d:100.17Hz)
  113. }
  114.  
  115.  
  116.  
  117. /*16bit高速PWM(DCファン制御25kHzPWM)*/
  118. //Timer1カウンター、比較レジスタを初期化
  119. TCNT1 = 0;
  120. OCR1A = 0;
  121. OCR1B = 0;
  122.  
  123. //高速PWM動作,Top値ICR1
  124. TCCR1B |= _BV(WGM12) | _BV(WGM13);
  125. TCCR1A |= _BV(WGM11);
  126.  
  127. //比較一致でLow、BOTTOMでHighをOC1A,OC1Bへ出力(非反転動作)
  128. TCCR1A |= _BV(COM1A1) | _BV(COM1B1);
  129.  
  130. //Top値
  131. ICR1 = 0x013f; //320=0x140,319=0x013f
  132. //(システムクロック8MHz分周なし)/(2*TCNT1分周*TOP値320)=12.5kHz
  133. //ノコギリ波割込み反転周期12.5kHz
  134. //OCR1A,OCR1B比較一致による周期25kHz
  135. //オシロ実測で25kHzに調整,ICR1=319=0x013f
  136.  
  137. //TCNT1クロック分周なし
  138. TCCR1B |= _BV(CS10);
  139. }
  140.  
  141. /*IOポート初期化*/
  142. void init_io (void) {
  143. PORTA = 0x03; // 00000011 PA0,PA1 PullUp
  144. PORTB = 0xe3; // 11100011 PB0,1,5,6,7 PullUp
  145. PORTD = 0x5c; // 01011100 PD2,3,4,6 PullUp
  146. PORTD|= _BV(PD1); //PD1 PullUp 50/60Hz切り替え
  147. DDRB = 0x00; // 00000000 PB3~4 はmainでbit操作
  148. DDRD = 0x00; // 00000000 PD1,5 はmainでbit操作
  149. }
  150.  
  151. /*システムクロック変更初期化*/
  152. //出荷時のヒューズビットCKSEL=0100, SUT=10, CKDIV8=0
  153. void init_sysclk (void) {
  154. //標準でCKDIV8=0のため8分周(CLKPS3~0を0011に設定)してしまう
  155. //念のため分周なしに初期化
  156. CLKPR = _BV(CLKPCE);//クロック分周変更許可
  157. CLKPR = 0x00; //分周なしに変更
  158. }
  159.  
  160. /*ピン変化割込み初期化*/
  161. //AC100Vのゼロクロス付近のHighトリガーをPB2に入力
  162. //PB2のピン変化0群について割込み許可設定
  163. void init_pin_int (void) {
  164. GIMSK |= _BV(PCIE); //一般割り込み許可レジスタ,ピン変化0群割り込み許可(PCIE)bit5
  165. PCMSK |= _BV(PCINT2); //ピン変化0群割り込み許可レジスタ,個別PB2を許可(PCINT2)bit2
  166. }
  167.  
  168. int main (void) {
  169. int i; //i:アドレスに関連
  170.  
  171. unsigned char pwm0 = 0;
  172. unsigned char pwm1 = 0;
  173. volatile unsigned char *dmx_buf;
  174.  
  175. /**デバイスを初期化**/
  176. init_sysclk();
  177. init_io();
  178. init_pwm();
  179. init_pin_int();
  180.  
  181. /**DMX base address**/
  182. //DipSWなどでIOポートのLowを数える
  183. //Address 256 128 64 32 16 8 4 2 1
  184. //i-bit 8 7 6 5 4 3 2 1 0
  185. //PORT PB7 PB6 PB5 PB1 PB0 PD6 PD4 PD3 PD2
  186. i = ((~PIND & 0x1c) >> 2); //0b00011100:PD4,3,2 :i-bit2,1,0
  187. i |= ((~PIND & 0x40) >> 3); //0b01000000:PD6 :i-bit3
  188. i |= ((~PINB & 0x03) << 4); //0b00000011:PB1,0 :i-bit5,4
  189. i |= ((~PINB & 0xe0) << 1); //0b11100000:PB7,6,5 :i-bit8,7,6
  190.  
  191. //処理中"dmx_recv.c"のdmx_ch値は0~511
  192. //dmx_buf[i-1]
  193. if (i) { //IOポートを2進法で数える
  194. dmx_buf = init_dmx(i - 1, DMX_SIZE);
  195. //"dmx_recv.c"のUSART初期化へ
  196. //"i-1"はchに、"DMX_SIZE"はsizeに
  197. }
  198. else if (!i) { //IOポートに入力がない場合512ch
  199. dmx_buf = init_dmx(512 - 1, DMX_SIZE);
  200. }
  201.  
  202. sei(); //デバイス初期化、ポート読み込み終わったので割り込みを許可
  203.  
  204. /*メインループ*/
  205. while (1) {
  206. wait_dmx(); //DMX受信完了
  207.  
  208. pwm0 = dmx_buf[0];
  209. pwm1 = dmx_buf[1];
  210.  
  211. //PD1High(PullUp):50,60Hz共通設定
  212. if(PIND & _BV(PIND1)){ //PD1がHighであれば
  213. if(pwm0 >=25){//pwm0が25以上になったとき
  214. if(pwm0==255){//ポンプ液送りのためFull
  215. OCR0B = 25;//0にするとゼロクロス地点を超えてしまい波形が乱れる
  216. }
  217. else{//Top値と調整,ポンプを目的上7割以上で稼働しない前提
  218. //OCR0B = 280 - (pwm0);//60Hzフルスケール,50Hzでは使用不可
  219. //OCR0B = 250 - ((pwm0)*7/10);//両周波数の最大公約
  220. OCR0B = 230 - (pwm0>>1);//50Hz75%程度基準,60Hz50%程度
  221. //OCR0B = 230 - ((pwm0)/3);//50Hz50%程度基準,60Hz40%程度
  222. }
  223. }
  224. else{ //pwm0が25未満のとき
  225. OCR0B = 255;//
  226. //クロック分周の制約上120Hzのところ130Hzなので超過する値を調整
  227. //8bitのOCR0Bとpwm0の値を反転させているので、
  228. //pwm0=25のとき,280-25=255で下限
  229. //pwmが25未満のときは下限の255にしておく
  230. }
  231. }
  232.  
  233. //PD1Low:東日本50Hz限定最適化
  234. if(!(PIND & _BV(PIND1))){//PD1がLowであれば
  235. if(pwm0==255){//ポンプ液送りのためFull
  236. OCR0B = 2;//0にするとゼロクロス地点を超えてしまい波形が乱れる
  237. }
  238. else{//Top値と調整,ポンプを目的上7割以上で稼働しない前提
  239. //OCR0B = 70-(pwm0>>2);//50Hzフルスケール
  240. OCR0B = 70-(pwm0>>3);//50Hz60%程度基準
  241. //OCR0B = 70-(pwm0>>4);//50Hz40%程度基準
  242. }
  243. }
  244.  
  245. //ACポンプ制御
  246. if((pwm0)&&(dmx_buf[1] >0x33)){ //ファンが20%(51:0x33)以上
  247. DDRD |= _BV(PD5); //ポートを出力に
  248. } else {
  249. DDRD &= ~_BV(PD5); //ポートを出力にしない
  250. }
  251.  
  252. //二重反転ファン25kHzパルス制御
  253. //PB3吸込み側,PB4吐出側
  254. if (pwm1) { //0じゃなければ
  255. OCR1A = (pwm1)*5/4; //255*5/4=318.75<319
  256. DDRB |= _BV(PB3); //ポートを出力にする
  257. } else {
  258. DDRB &= ~_BV(PB3); //ポートを出力にしない
  259. }
  260. if (pwm1) { //0じゃなければ
  261. OCR1B = (pwm1)*5/4; //255*5/4=318.75<319
  262. DDRB |= _BV(PB4); //ポートを出力にする
  263. } else {
  264. DDRB &= ~_BV(PB4); //ポートを出力にしない
  265. }
  266. }
  267.  
  268. }
Add Comment
Please, Sign In to add comment