トピック関連記事
48時間以内の記事は New Mark で表示されます
続続ーPWM
TRさん,こんにちは。また,スレ深くなったの,新しくします。

今日は,PWMの基本周波数の変更のプログラムいじってました。

以前掲載したときは,HITECHのコンパイラ用でしたので,
XC8用に変更してました。

正直面倒くさいですね,新しいコンパイラ用に書き換えるのは。


さて,前掲のデジタルポテンショメータの使い方ですが,

使い方をのせていた諸兄は,Arduinoでプログラム組んでいるようですね。

多分,直接,SECさんの基板等との接続は難しいでしょうね。

でも,PWMの出力を使えば,コントロールはできそうに思います。

いくつか方法あると思いますけど,

 MACHのPWM出力→→フィルターで直流変換→→

   PICでAD変換→→PICで抵抗のUP・DOWN

と,できないことないかとは思いますけど,ちょっと時間かかりるかなあ。

PWMを直流で受けてAD変換したものを使ってる諸兄は,

下記です。

http://www002.upp.so-net.ne.jp/hard-and-soft/Spindol_Control/Spindol_Control.html

操作的には,2本の線のそれぞれをHIGHT LOWにするだけですから,PICでもそれほ難しくないと思います。

ただ,それよりも,AD変換した数値と設定抵抗等の関係,
いち調べるのに時間かかるかもですね。
mabo 2019/05/22(Wed) 14:45 No.1485
Re: 続続ーPWM
maboさんこんばんは。
今日は仕事でした。 再雇用ですね。

>PWMの基本周波数の変更のプログラムいじってました。


弄っていたプログラムは、ご紹介くださった以下URLのプログラム(PWM周波数変換プログラムと呼ぶかな?)
ですか?


素早いですね!


このプログラムは、smoothsutepperから出るPWMの周波数を変えるというものですよね?
違いますか?


で、maboさんが、
>MACHのPWM出力→→フィルターで直流変換→→

   PICでAD変換→→PICで抵抗のUP・DOWN

と,できないことないかとは思いますけど,ちょっと時間かかりるかなあ。


と言っているのは、
PWM変換プログラムの変換後のPWMのところを、→ PICでAD変換→→PICで抵抗のUP・DOWN

ということですか?
考えもつきませんでした。
PWMという、波形をRCフィルターを通すとアナログに戻るなんてびっくりでした。


>PWMを直流で受けてAD変換したものを使ってる諸兄は,

RCフィルターでアナログの電圧に戻し、アナログ電圧をPICのAD変換機能を使って更にPWM化するとは!!

でもでも、
>PICでAD変換→→PICで抵抗のUP・DOWN

こんなことって、PICで出来るのですか??
ワクワクしてきました。
キットで遊ぼうのレベルです。 本にそういった方法はありましたか?
TR   2019/05/22(Wed) 19:32 No.1486
Re: 続続ーPWM
TRさん,こんばんは。

>>PICでAD変換→→PICで抵抗のUP・DOWN

>こんなことって、PICで出来るのですか??

紹介したデジタルポテンショメータがつかえるのであれば,

2本の線をHIGHT・LOWにするだけですから,

キットで遊ぼうのLチカとそれほど変わらないと思います。

やることは,

 (1)AD変換の数値をPICで受け取る
  ↓
 (2)数値を保存
  ↓
 (3)AD変換の数値をPICで再び受け取る
  ↓
 (4)前回保存した数値と比較する
  ↓
 (5)数値が変化or変化しない
      ↓       ↓
      ↓      (1)へ
    二つの端子の操作
      ↓
     (1)

 みたいな感じですかね。

 これと同じようなことやるのに,

 デジタルポテンショメーターの代わりに,LEDを二つ使って,

 疑似の回路とプログラム作れると思います。

 具体的には,

 https://keitetsu.blogspot.com/2014/11/16f88-xc8-led.html

 と同じプログラムと同じ回路で,LEDを一つ増やして,

 読み込んだ,AD変換の数値で,保存した数値の比較して,
 数値が多くなったら,AのLEDをつけて消す,

数値が少なくなったら,BのLEDをつけて消す。

 ということができれば,大丈夫でしょうね。

 このプログラムで使ってるPWMはつかいませんので,もっと簡単になると思います。

 実際の運用では,もうちょっと,考慮しなければいけないことあると思いますが,

 ボリュームの部分をMACHからのアナログ変換したPWM信号へ,LEDの部分をデジタルポテンショメーターのアップダウンの端子へ,

 ということで,キットで遊ぼうと同じよようなレベルで可能だと思います。

 TRさんのお手持ちの材料でできますよ。

 PICはAD変換の機能があるのならなんでもいいかな。
mabo   2019/05/22(Wed) 22:00 No.1487
Re: 続続ーPWM
maboさん、おはようございます。

いいですね、グットアイディアですね。


> (2)数値を保存
  ↓
 (3)AD変換の数値をPICで再び受け取る
  ↓
 (4)前回保存した数値と比較する

●●●・・・

この肝となる部分をどうプログラムするのでしょうか?
幸いにも、以前、ここで、クーラントポンプを可変VRで制御するC言語を教えていただいたので、
これを基礎に頑張りたいと思います。
どうか、ご教授願います。
TR   2019/05/23(Thu) 06:21 No.1488
Re: 続続ーPWM
TRさん,おはようございます。

今日の夜から泊まりがけで,ちょっと遠出しますので,

レス時間空くと思います。

具体的なプログラムですが,

https://keitetsu.blogspot.com/2014/11/16f88-xc8-led.html

のプログラムの

 while(1){
  setADCChannel(0);
  __delay_us(50);
  duty1 = readADCValue();
 setPWM1Duty(duty1);
 }

コメントは外してありますが,ここを次のようにいじれば,

とりあえずは形になると思います。

具体的には,

 int hozon=1024;
 int newhozon=1024;
while(1){
     setADCChannel(0);
     __delay_us(50);

     if(hozon ≠ readADCValue()){
       newhozon=readADCValue();
       RB2=0;//CSピンコマンド待ち

      for(i=0;i<abs((hozon-newhozon)/100));i++){
       if((hozon-newhozon)>0)
        RB3=1;//U/Dピンをアップに設定
        increse();
       }
       if((hozon-newhozon)<0)
        RB3=0;//U/Dピンをダウンに設定
        increse();
      }
      RB2=1;//メモリー書き込み
  }
      
 }

increse{
RB1=0;
__delay_us(10);//調整の必要ありそう
RB1=1;
}


AD変換で受け取る数値は,多分0〜1024ぐらいでしょうから,

これを10段階ぐらいに分けて,それに応じて,アップダウン
するという感じです。

実装するには,いろいろ考えないとだめだと思います。

AD変換の受け取り方は,

http://www002.upp.so-net.ne.jp/hard-and-soft/Spindol_Control/Spindol_Control.html

の方のように平均をとる必要があるかもしれません。

それから,デジタルポテンショメーターの操作で,

どのくらいの信号を送ればいいのか,

一回の操作で抵抗はどの程度変化するのか,

実験かデータシート等で確認する必要があると思います。

===追伸===

 諸兄のデータ見たら,3本の線のコントロール必要ですね。
 
 LEDは,二つ増やす必要ありですね。
mabo   2019/05/23(Thu) 10:06 No.1489
Re: 続続ーPWM
maboさん、ありがとうございます。

お出かけということですね。
よく読んでみます。分からない点が多々出てくると思います。
その節は勘弁してください。
気をつけてお出かけください。



追記
ところで、このプログラムに使っているPICは16F88ですか?
教えてください。
TR   2019/05/23(Thu) 11:08 No.1490
Re: 続続ーPWM
TRさん,こんばんは。

レス遅くなりました。

はい,使ってるのは,16F88です。

でも,AD変換のあるものなら,

何でもいいと思います。

できれば,新しいのがいいかも。

16F88では,PICKIT 4は使えません。

もう,サポートの対象からはずれたんでしょうね。

いろいろ部品が届いてるので,

また,ぼちぼちやります。
mabo   2019/05/24(Fri) 23:34 No.1491
Re: 続続ーPWM
maboさんこんにちは。
鉄ちゃん
https://keitetsu.blogspot.com/2014/11/16f88-xc8-led.html?m=1
プログラム中程にある
次の事の意味分かりますか?
duty1 = readADCValue();
空のカッコ、こういった使い方は、初めてです?
お願いします。
TR   2019/05/25(Sat) 18:40 No.1492
Re: 続続ーPWM
TRさん,こんばんは。

サブ関数に以下のようにあります。

unsigned int readADCValue(void)
{
GO_nDONE = 0b1;
while(GO_nDONE);
return ((ADRESH << 8) + ADRESL);
}

括弧のなかが void になっていますので,

因数に何も渡さないの意味になります。

何も書かないのと同じ意味です。

unsigned int readADCValue(void)

を,

unsigned int readADCValue( )

と書いてもも同じです。


duty1 = readADCValue();

ですが,

これは,AD変換で,抵抗値を読みとった値を,

duty1

に代入の意味です。
mabo   2019/05/25(Sat) 21:40 No.1493
Re: 続続ーPWM
鉄ちゃんおプログラムは何をしようとしているのでしょうか?
題目には、
可変抵抗(RA0)でLEDの輝度(RB3)を制御する
とありますが、
AD変換をした値(duty1)をPWMを発生させていますが、
duty1 = 0;
として、初期化をしたのち、
duty1 = readADCValue(); // A/D変換値を取得
とか、 setPWM1Duty(0);
とか、関数を作って複雑化しているように思えます。

自分も、以前、可変抵抗の電圧を読み取って、読んだ値を
ADRESに格納し、ADRESの値を使って、PWMを発生させましたが、
もっと単純だったはずなのにです。


デジタル抵抗と何か関係がるのでしょうか?
TR   2019/05/26(Sun) 18:40 No.1494
Re: 続続ーPWM
TRさん,こんばんは。

>デジタル抵抗と何か関係がるのでしょうか?
ですが,鉄ちゃんさんのプログラム,

一部分を改変すれば,デジタルポテンショメータのコントロール
に使えそうだ,

ということで,ご紹介しました。

使うのは,AD変換の部分で,PWMの部分はつかいませんが。

考え方として,鉄ちゃんさんの main() の

while(1)の部分を,1489のスレのように書き換えれば,

LEDを合計3つ使って,デジタルポテンショメータの実機がなくても,

シュミレートできそうです,ということでの紹介でした。

同じ,一つのことをするプログラムにも,多分,いくつかの書き方があるように思います。
mabo   2019/05/26(Sun) 21:18 No.1495
Re: 続続ーPWM
maboさん、おはようございます。

No1487の以下の内容は、鉄ちゃんのプログラムでいうとどの部分になりますか?
******
 (1)AD変換の数値をPICで受け取る
  ↓
 (2)数値を保存
  ↓
 (3)AD変換の数値をPICで再び受け取る
  ↓
 (4)前回保存した数値と比較する
  ↓
 (5)数値が変化or変化しない

******



追記
今回は、
電圧読み取りの変化の確認は、タイマー0割込みですかね〜?
TR   2019/05/27(Mon) 07:10 No.1496
Re: 続続ーPWM
maboさんすみません。
次の意味を教えてください。

void setADCChannel(unsigned char channel)
{
ADCON0 &= 0b11000111; // bit5~3,CHS<2:0>を初期化(電圧読み取りピンRA0設定だが&=により000)
ADCON0 |= (channel << 3);//上で初期化後、3bit左にシフト?
TR   2019/05/28(Tue) 06:08 No.1498
Re: 続続ーPWM
TRさんこんにちは。

おたずねの件ですが,次のような感じです。

間違いあるかもしれませんが。

コメントみてください。

 int hozon=1024;
 int newhozon=1024;
while(1){
     setADCChannel(0);//読み込みチャンネルの設定
     __delay_us(50);

     if(hozon ≠ readADCValue()){//データを読み込んで保存データと読み込みデータの比較
       newhozon=readADCValue();//保存したデータと違ったら保存
       RB2=0;//CSピンコマンド待ち

      for(i=0;i<abs((hozon-newhozon)/100));i++){
       //以下の部分で,変化に応じた処理
       if((hozon-newhozon)>0)
        RB3=1;//U/Dピンをアップに設定
        increse();//ボリュームを移動
       }
       if((hozon-newhozon)<0)
        RB3=0;//U/Dピンをダウンに設定
        increse();//ボリュームを移動
      }
      RB2=1;//メモリー書き込み
  }
      
 }

increse{
RB1=0;
__delay_us(10);//調整の必要ありそう
RB1=1;

みたいな感じで,while(1)の中で,読み取り,比較,処理

をしてます。

それから,

void setADCChannel(unsigned char channel)
{
ADCON0 &= 0b11000111; // bit5~3,CHS<2:0>を初期化(電圧読み取りピンRA0設定だが&=により000)
ADCON0 |= (channel << 3);//上で初期化後、3bit左にシフト?

ですが,ADCON0 の4ビット目から6ビットで,読み取りチャンネルの設定をするために,

&をとって,4〜6ビット目をにしてます。

ADCON0 |= (channel << 3)

は,読み取りチャンネルを channel で受けとって,

ADCON0 の4〜6ビット目にセットするために,

左に,3つシフトさせてます。

それから,AD変換では,割り込みを使う方法もあるようですが,

鉄ちゃんさんのプログラムで,AD変換では,割り込みは使ってないようです。
mabo   2019/05/28(Tue) 13:15 No.1499
Re: 続続ーPWM
setADCChannel(0);
引数0にし関数が呼び出され、
ADCON0 |= (channel << 3);
とあるが
0を左に3ビットシフトしたものと、
ADCON0とどうやって代入演算するのですか?
しかし、電圧読み取り端子がどうして、関係するのか?
電圧読み取り端子を変えるには必要があるのか?

多分、
0とADCON0を合成してADCON0にある1をひきだすんだ!

追記 5/29 13:20
0を引数にしているので、
001|=000は、001なので、RA0が、ADCON0の3〜5ビットにセットされる。

TR   2019/05/28(Tue) 14:11 No.1500
Re: 続続ーPWM
setADCChannel(0);
この関数は、ADコンバーターの設定をすれば、不用?
理由
読み取り端子は固定なので。


      for(i=0;i<abs((hozon-newhozon)/100));i++){
100で割る意味?

increse();
この関数の使い方?スケッチの書き方?
TR   2019/05/28(Tue) 16:25 No.1501
Re: 続続ーPWM
increas();この関数は、ボリュームということですから、
ひょっとして、No1487中 ↓
 数値が多くなったら,AのLEDをつけて消す,

数値が少なくなったら,BのLEDをつけて消す。

この内容を示しているのでしょうか?

追記  ↓ですね?(英訳したら増大という意味だったので、電圧が増えるときの関数だと思っていました。

increse{
RB1=0;
__delay_us(10);//調整の必要ありそう
RB1=1;
TR   2019/05/29(Wed) 07:07 No.1502
Re: 続続ーPWM
まねて、ちょっと変えて、以下の通りやってみましたが
ダメでした。
if分の書き方を変えています。
16F1827です。

/*RB4で電圧読み取り*/
//RB7が汎用出力14番_SEC基板ポート2のSL-18の1番ピン(出力端子)を入力端子として受ける
//RA1が電圧UPのモニターLED緑で点滅させる
//RA0は電圧DownのモニターLED黄で点滅させる
//RA2はデジタル抵抗のCSピンへ
//RA3はデジタル抵抗のU/Dピンへ
//RA4はINCピンはプルアップで常時HIにする
//PIC16F1827 Configuration Bit Settings

// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
// クロック周波数指定
// (__delay_ms()関数が必要としているため)
#define _XTAL_FREQ 16000000
// プロトタイプ宣言
unsigned int adconv(void); //ADC読み込み関数
// メイン関数
void main(void) {
OPTION_REGbits.nWPUEN = 0; //内部プルアップ有効
OSCCON = 0b0111001; //クロック周波数を16MHzに設定
PORTA = 0x00; //全てLo
PORTB = 0x00; //全てLo
ANSELA = 0b00000000; //全てデジタルI/Oとする
ANSELB = 0b00010000; // 可変抵抗の電圧読み込み用にRB4のみアナログ
// 入出力設定
TRISA = 0b00000000; // RA全て出力
TRISB = 0b10010000; //RB4 可変抵抗用ADC用入力端子
// ADコンバータ設定
ADCON0 = 0b00100001; // アナログ変換情報(RB4から読込む)
ADCON1 = 0b11010000; // 読取値は右寄せ、A/D変換クロックはFOSC/16、VDDをリファレンスとする
//変数宣言
int i;
int hozon=1024;
int newhozon=1024;
while (1) {
adconv();//adc 読み込み関数呼び出し
__delay_us(50); // アクィジション時間(50マイクロ秒)
if(hozon!= adoconv()){
newhozon=adconv();  
       RA2=0;//CSピンコマンド待ち

for(i=0;i<abs((hozon-newhozon)/100));i++){
if((hozon-newhozon)>0){
        RA3=1;//U/Dピンをアップに設定
        LATA1=!LATA1;
__delay_us(100);//調整の必要ありそう
LATA1=0;
      
      else if((hozon-newhozon)<0){
        RA3=0;//U/Dピンをダウンに設定
        LATA0=!LATA0;
__delay_us(100);//調整の必要ありそう
LATA0=0;
}
else{      
RA2 = 1; //CSピン_メモリー書き込み(ワイパー姿勢を保存します。)
}
}
}
}


// アナログ値の変換と読込み処理関数

unsigned int adconv() {
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ
return ADRES;
}
TR   2019/05/29(Wed) 21:30 No.1503
Re: 続続ーPWM
TRさん,こんばんは。

いろいろやっておられますね。

亀レスですみません。

>setADCChannel(0);

ですけど,これ while ループの中で設定してますよね。

意図があるのか分かりませんが,

一度設定したら,OKかもしれませんね。

それから,

>for(i=0;i<abs((hozon-newhozon)/100));i++){
100で割る意味?

の100で÷意味ですが AD 変換で読み取った数値
で,抵抗を10段階で調整しては,ということで,
100でわりました。

AD変換の読み取りの数値は,0〜1024までの数値という
ことでやりましたが,この上の読み取りだと,
変更ですね。

それから,

increse{
RB1=0;
__delay_us(10);//調整の必要ありそう
RB1=1;
}

かっこが抜けてましたね。

  誤 increse{
  正 increse(){


1827プログラムはちょっと,みてみますね。


PWMの基本周波数変更

  100Hz→10kHz

のプログラムでもがいていました。

原因は,PWM発生機のようで,

DUTY比0にしても,パルスが出たりでなかったりです。
mabo   2019/05/29(Wed) 21:59 No.1504
Re: 続続ーPWM
>原因は,PWM発生機のようで,

DUTY比0にしても,パルスが出たりでなかったりです。


不良品でしたね。
原因が分かってよかったですね。


ADチャンネルは、電圧読み取り端子の設定だと思うので、
プロトタイプ宣言はせずに、簡単にします。
方法
// ADコンバータ設定
ADCON0 = 0b00100001; // アナログ変換情報(RB4から読込む)
ADCON1 = 0b11010000; // 読取値は右寄せ、A/D変換クロックはFOSC/16、VDDをリファレンスとする


プログラムのエラーは、
多分、AD変換後の比較方法にあるような気がします。
その部分が、赤くなっています。

何度かえてみてもうまくいきません。
お知恵拝借します。
どうぞ、宜しくお願いします。
TR   2019/05/30(Thu) 07:32 No.1505

処理 記事No 暗証キー

- JoyfulNote v6.02 -
++ Edited by Hamel ++