トピック関連記事
48時間以内の記事は New Mark で表示されます
続続続ーPWM
TRさん,こんにちは。

頑張っておられますね。

PWM発生機は不良品ではなくて,仕様みたいな感じです。

ところで,1503のTRさんのプログラムですが,

いくつか追加と修正点で,シンタックスエラーはなくなり,

コンパイルも通るようになりました。

追加は,abs()の組み込み関数を使うためのライブラリーのインクルードです。

数学系の関数や,文字操作の組み込み関数?を使うときは,

専用のインクルードファイルを取り込まないとだめみたいです。

それから,else は,二つあるとだめみたいです。

思うようにいかなかったのは,全角の空白が入ってました。

以下が一応,エラーのなくなったプログラムです。

/*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>
#include <stdlib.h>
#include <math.h>

unsigned int adconv(void) ;//ADC読み込み関数
void main(void);




// クロック周波数指定
// (__delay_ms()関数が必要としているため)
#define _XTAL_FREQ 16000000
// プロトタイプ宣言

//メイン関数
void main(void){

int i;
int hozon=1024;
int newhozon=1024;

//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をリファレンスとする



while (1) {
hozon=adconv( );//adc 読み込み関数呼び出し
__delay_us(50); // アクィジション時間(50マイクロ秒)

if(hozon != adconv( )){
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(void) {
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ
return ADRES;
}


シンタックスエラー等はなくなりましたが,

実際に思った動作をするかどうかは,たしかめで,

アルゴリズム等,考える必要あるかもしれません。

時間みて,私も,LEDでシュミレートしてみます。
mabo 2019/05/30(Thu) 11:04 No.1506
Re: 続続続ーPWM
maboさん有り難うございます。
一人でもがいていました。


for(i=0 ; i < (abs(hozon-newhozon)/100) ;&#160;

これですが、デジタルポテンションメーターを使う場合、/100は不用?

ledの実験楽しみに待ちます。
後、デジタルポテンションメーターに繋げばOK?


それと、absを使うためのライブラリー
stdlb.hですね?
TR   2019/05/30(Thu) 13:06 No.1507
Re: 続続続ーPWM
maboさん、続けて失礼します。
UP/DOWNのモニター用LEDのプログラムを少し変えて、実験しましたが、、
RB4(SEC基板PORT2の14番)のHi/Loに連動しません。

狙った動作 ↓

RB4 HI→LATA1がHiでLATA0がLo
RB4 Lo→LATA1がLoでLATA0がLo


上の問題もあるのですが、
ご紹介をいただいたURLのデジタル抵抗の使い方を見ると
****
SPIのようにCSピンがLoになるとコマンド入力待ちなり、INCピンの立下りエッジでRw/Vw端子が移動します。
更に、U/DピンがHi→大きい方へ
   U/DピンがLo→小さい方へ
****
となっています。

で、
MACH3の信号(SEC基板PORT2の14番)をU/Dに繋げますが、CSピンをLoにするにはどうしたらよいのでしょうか?
プログラムで、PICの端子をLoとし、
その端子をCSピンにつなぐのでしょうか?


追記

今、可変抵抗をつけて実験したら、まったくモニター用LEDが点滅しなくなりました。
タクトSWの時は点滅したのに!!

今気が付きました。
プログラムに あった ↓
newhozon=adconv( );
RA2=0;//CSピンコマンド待ち
TR   2019/05/30(Thu) 21:24 No.1508
Re: 続続続ーPWM
TRさん,こんばんは。

早いですね。いろいろなさってますね。


当たり前ですが,マニュアルあるようです。

http://www.farnell.com/datasheets/18974.pdf

これにもあるのですが,使う抵抗によって,一度に動かせる
数値が決まってるようですね。

X9C102 1KΩ 10.1Ω 40Ω
X9C103 10KΩ 101Ω 40Ω
X9C503 50KΩ 505Ω 40Ω
X9C104 100KΩ 1010Ω 40Ω

これとの兼ね合いで,どの程度の精度で動かすのか,
によって,

>for(i=0 ; i < (abs(hozon-newhozon)/100) ;&#160;

>これですが、デジタルポテンションメーターを使う場合、/100は不用?

の/100の数値は決めるようでしょうね。


>それと、absを使うためのライブラリー
>stdlb.hですね?

#include <stdlib.h>

でしたね。この辺私もその都度調べてます。



それから,TRさん,まだSECの基盤にはつながない方がいいです。

SECさんの基盤とつなぐのは,PICでの動作が正常に動くようになってからの方がいいと思います。

それから,SECさんの基盤とつなぐのは,PWMの出力を
アナログ変換した信号を取るものだけです。

>CSピンをLoにするにはどうしたらよいのでしょうか?

これは,MACHからの信号をプログラムで判断して,
PICで操作です。

MACH−−−−−PIC−−−−−デジタルポテンショメーター
    2本の線     3本の線

みたいな感じです。

マッハからの信号をボリュームでシュミレート。

PICからデジタルポテンショメーターへの3本の線の

信号を3つのLEDシュミレートという感じです。


ーーー追伸ーーー

 今,シュミレートのプログラムと,ハードを組み立ててます。

MACHからの信号読み取るのに,LCDで表示するための

準備してます。

これも,ちょっと面倒で,ちょっと,時間かかります。

環境ができれば,あとはシュミレートして,不具合を修正

すればいいと思いますので,時間がかかるかと思いますけど,

できそうな気がします。
mabo   2019/05/30(Thu) 22:49 No.1509
Re: 続続続ーPWM
maboさん、おはようございます。
自分ですが、年齢とともに、こういった分野に興味がわいてきています。
バイクとPICに、今は、興味津々です。

当方のレスは、写真の関係で2つに分けます。

先ず、その1
>これにもあるのですが,使う抵抗によって,一度に動かせる
数値が決まってるようですね。

データシートですが、グーグル翻訳でみると、
多分写真のところでしょうかね。
でも、maboさん、英語も分かるんですね!!

データシートの赤部分 ↓
FEATURES
100 Wiper Tap Points

となっているから、100で割っているんですね。
つまり、100単位、でも、1024を100で割るのかな〜?
100Ω単位なら、違うような気もしますが、はっきりとしません。
可変抵抗のBカーブならいいような、下限値40Ωを除いて1024としても、1024は約1000なので、
いいような気もします。
本来は、40Ω分を除くかな?
以前、猛牛ロックさんが、自分のクーラントポンプの時に、計算してくれた表がありましたよね。
No1388にあります。

TR   2019/05/31(Fri) 08:12 No.1510
Re: 続続続ーPWM
その2

>それから,SECさんの基盤とつなぐのは,PWMの出力を
アナログ変換した信号を取るものだけです。


繋ぎ方は 、図面をアップしますので、見て頂けませんか。m(__)m
現在は、SEC基板からの信号をテスト用のコンタクトSWとテスト用 2の可変抵抗でやっています。
※ テスト用 2の可変抵抗だと全くLEDが点滅しません。
変えたプログラム末尾に!
補足
PICのヘッダー
//RB4が汎用出力14番_SEC基板ポート2のSL-18の1番ピン(出力端子)を入力端子として受ける
//RA1が電圧UPのモニター赤LEDで点滅させる
//RA4はデジタル抵抗のCSピンモニター用の緑LED   ※ 新たに追加!!!
//RA0は電圧Downのモニター黄色LEDで点滅させる
//RA2はデジタル抵抗のCSピンへ
//RA3はデジタル抵抗のU/Dピンへ
//INCピンはプルアップで常時HIにする


凄いのができそうですね。
LCDモニターがよさそうですね。
自分のレベルでは難しいかな〜。
ワクワクしてきました。


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

TR   2019/05/31(Fri) 08:15 No.1511
Re: 続続続ーPWM
MABOさん、TRさん、ご無沙汰してます。

えーと、TRさんのX9Cですけど、基本的に3本制御ですね。2本でも可能なようですけど

データシートの3ページの表(Mode Selection)を見る限り、その接続ではWIPERを上げ下げ出来ません。
2本にしたいのならCSピンをGNDに接続して固定します。
(但し、その使い方では位置は記憶できません。)
で、U/Dピンを選択して、INCピンを下げた時にストローブです。

もう一点、この類のICは非常に出力が小さいです。
(出力可能な電圧は1mAほど。損失も10mW以下にする必要があります)
モーター側の電圧が5Vらしいので、多分ADCで入力していて大丈夫のような気はしますけど、
簡単なテストをしておいた方が良いです。

※本来、7ページ(Basic Circuits)に載っているように、オペアンプでバッファを取り、出力を増強させて使います。

ついでに言えば、折角のPICですから、こういった時はPIC16F1705のようなDACの付いたマイコンを使うのが良いです。
DACの付いているPICの殆どがオペアンプもあります。つまり、内部でオペアンプに繋いで安定した電圧で
出力する事が可能です。(といってもそんなに能力は無いでしょうけど)
これは、UNOあたりのArduinoには出来ない芸当です。
1705で、8ビットのDACですから、256段階で指定できることになります。
当たり前ですけど、ピンの上げ下げをすることなく、レジスタに値を入れるだけです。
(といっても、使いこなすには経験が必要でしょうけど→私も使った事はありません)
※添付図は1705のデータシートから。

猛牛ロック   2019/06/01(Sat) 02:15 No.1512
Re: 続続続ーPWM
猛牛ロックさん、ご薫陶感謝申し上げます。
ここ数日、プログラムを考えていました。
No1506のプログラムですが、思うように動作しません。
No1506は、そのほかにも ↓ 
//else{      
RA2 = 1;//CSピン_メモリー書き込み(ワイパー姿勢を保存します。)
//}
上のように、// 〇〇〇//
というように//で囲っています。

そこで、Swtich関数を使って、以下のようにしましたが、
それでも、思った動作をしません。
すみませんが見て頂けませんかm(__)m。


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

// CONFIG1
   略
#include <xc.h>
#include <stdlib.h>
#include <math.h>
// プロトタイプ宣言
unsigned int adconv(void); //ADC読み込み関数
void main(void);
// クロック周波数指定
// (__delay_ms()関数が必要としているため)
#define _XTAL_FREQ 16000000
//メイン関数

void main(void) {
int i;
int hozon = 1024;
int newhozon = 1024;
//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 a = hozon - newhozon;
while (1) {
hozon = adconv(); //adc 読み込み関数呼び出し
__delay_us(50); // アクィジション時間(50マイクロ秒)
if (hozon != adconv()) {
newhozon = adconv();
switch (a) {
case 'a' > 0:
for (i = 0; i < (abs(hozon - newhozon) / 100); i++) {
RA2 = 0; //CSピンコマンド待ち
RA3 = 1; //U/Dピンをアップに設定
LATA0 = 1;//黄色LEDダウンモニター
break;
}
case 'a' < 0:
for (i = 0; i < (abs(hozon - newhozon) / 100); i++) {
RA2 = 0; //CSピンコマンド待ち
RA3 = 0; //U/Dピンをダウンに設定
LATA1 = 1;
break;
}
default:RA2 = 1;//CSピンHi
break;
}
}
}
}


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

unsigned int adconv(void) {
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ
return ADRES;
}
TR   2019/06/01(Sat) 07:23 No.1513
Re: 続続続ーPWM
TRさん,猛牛ロックさんおはようございます。

猛牛ロックさん,ご意見いただけると,心強いです。

TRさん,回路図のことは,読み取りができず,アドバイス等

とんでもない話ですけど,

MACHからの信号には,

抵抗とコンデンサー入れる必要あるようです。

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

に回路図のってます。

私の環境で,もがきました。

詳細は,今夜書きます。

if(hozon != adconv( )){ }

がだめでした。ADCの読み取りが安定しませんでした。
mabo   2019/06/01(Sat) 07:49 No.1514
Re: 続続続ーPWM
プログラムは↑で言ったように、接続が違います。
で、上では3線コントロールが良いように言いましたけど、
値を保存してもいい事も無い気がします。つまり、csピンはプルダウンが良いです。
(電源を入れた時に一瞬動くことになるかもしれません)

MachからのPWM信号をフィルタを通してからアナログで取得としているようですけど、
フィルタを通しても値は振動します。振動させないようにするには、抵抗値とコンデンサの容量を大きくする必要がありますけど、
その場合は反応の遅さとして表れます。どの位が適しているかは、Machからの信号の周波数が元になります。
私の好みとしてはデジタルでそのまま読み取る方法かなぁ。


で、プログラムを見てみましたけど、実際の回転数が無いですよね?
構成としては、通常、
Machから何rpm(或いは停止)の命令が来たかの判断
つまり、ターゲットとなる回転数が決まります。

次にその回転数になるようにボリュームを操作するのでしょうけど、
現在が何rpm出ているのかを取得しないと、プログラムを繋げようがないです。
或いは、適当にrpmを100段階(抵抗の分解能)にしようとしているのでしょうか?

もし今、回転数計が付いていないなら、付けてみる機会だと思います。

プログラムは、大体、下記のような感じかと思います。


#define ud LATA○
#define inc LATA×


//外部変数
volatile char x9c_val;

void x9c_init(void){
ud=0;
for(char i=0;i<99;i++){
inc=0;
__delay_us(1);
inc=1;
__delay_us(500);
}
x9c_val=0;
}

void x9c_up(void){
ud=1;
inc=0;
__delay_us(1);
inc=1;
if(x9c_val<99)x9c_val++;
//次の上げ下げは500us空ける
}


void x9c_down(void){//TYPOを修正
ud=0;
inc=0;
__delay_us(1);
inc=1;
if(x9c_val>0)x9c_val--;
//次の上げ下げは500us空ける
}

void main(){

//略

x9c_init();
while(1){
static unsigned int adc[4]={0};
static char num=0;
unsigned int target=0;
adc[(++num)&3]=adconv();
for(char i=0;i<4;i++)target+=adc[i];
target/=40.9;

if(target>x9c_val)x9c_up();
else if(target<x9c_val)x9c_down();
__delay_ms(1);//TYPO修正
}
}
猛牛ロック   2019/06/01(Sat) 18:12 No.1515
Re: 続続続ーPWM
猛牛ロックさん,今晩は。

すっきりとしたプログラムありがとうございます。

多分,実際の使用を想定しプログラムですね。

私は,今,タイミングチャートは,ちょっと,度外視してます。


for(char i=0;i<4;i++)target+=adc[i];
target/=40.9;

部分は,移動平均でしょうか。


私がもがいてるのは,その前の段階で,動作をLED,LCDで,確認している段階です。

とりあえず,U/DとINCの2本の線の動作を頭においてます。

実際使うとなると,ワイパーの保持とか,ワイパーの閾値の処理とか,まだ未知の部分が多いので,とりあえずはというところです。

それから,

>その場合は反応の遅さとして表れます。どの位が適しているかは、Machからの信号の周波数が元になります。
>私の好みとしてはデジタルでそのまま読み取る方法かなぁ。

そうですね。デジタルを直接読み取るには,ちょっとプログラム組まないとですね。

PWMの基本周波数の変換のプログラムを移植しましたが,
理解するのに時間かかって,手こずりました。

その点,アナログでの受け取りは,反応速度の問題もあるでしょけど,ADCで読み取れるので,お手軽でしょうかね。

それと,MACHで,RPMの情報は,直接でてるのでしょうか。

ただ,RPMの情報あったとしても,それをもとにコントロールするとなると,PIDの調整等が必要でしょうから,

ちょっとハードルたかいかな,なんて思います。

>現在が何rpm出ているのかを取得しないと、プログラムを繋げようがないです。
>或いは、適当にrpmを100段階(抵抗の分解能)にしようとしているのでしょうか?

私個人は,とりあえず,10段階ぐらいの範囲で,スピードが
調整できればいいかなと思いました。



TRさん,こんばんは。

1514でも書きましたが,

if (hozon != adconv())

がだめでした。

ここを

if(abs((buffer-hozon))>10)

保存した物と現在の値が10以上ひらいたら,

という風に変更したら,まずは,動きました。

それとTRさんのプログラは,最初から完成形,みたいに,
必要なこと全部盛ってるような気がします。

全部盛り込んで,不具合を修正するやり方もあると思います。

なかなか,不具合見つけるの大変だと思います。

私は,逆のやり方で,必要なことを一つ一つ確認して,

全体を仕上げていく感じでやってます。

取り合えず動作の確認できた,私のプログラムです。

電圧の変化に応じて,U/Dの動作を

  UP→LED点灯
  DOWN→消灯

で,

INCを100mvではなく,10mvの変化で一回点滅,

ということで,確かめました。

下記がそのプログラムですが,ちょっと猛牛ロックさんの前では,

恥ずかしいです。

while(1){
setADCChannel(0); // A/D変換対象チャンネルを設定

buffer = readADCValue(); // A/D変換値を取得

itoa(str,hozon,10);
lcd_clear(); //表示クリア
lcd_setCursor(0, 0);
lcd_puts(str);
lcd_puts("mV");

__delay_us(50);

if(abs((buffer-hozon))>10){
newhozon=buffer;

itoa(str1,newhozon,10);
lcd_setCursor(0, 1);
lcd_puts(str1);
lcd_puts("mV");

if( hozon > newhozon ){
U_D=HIGHT;
increse((hozon-newhozon)/10);
}
if( newhozon > hozon ){
U_D=LOW;
increse((newhozon-hozon)/10);
}
hozon=newhozon;
}
}
}

void increse(int ohom){
int i;
for(i=0;i<ohom;i++){
INC=LOW;
__delay_ms(100);
INC=HIGHT;
__delay_ms(1000);
}
}
mabo   2019/06/01(Sat) 22:45 No.1516
Re: 続続続ーPWM
プログラムの中で「ワイパー位置」を基準(意識したもの)にした方が良いです。

このプログラムではADC値(1024分割)が基準になっていて、ワイパー(100分割)の位置が意識されていません。
X9Cは操作は簡単と言えますけど、絶対位置が無いのでワイパー位置は自分で管理する必要があります。
(現在、ポテンショメータの両端を行き来するような動きになると思います)
その辺りは絶対位置で指定できるタイプの方が簡単です。

→初期化(0もしくはMAXの位置を割り出)して、記憶させる必要があります。


で、根本的な事になるのですけど、
10kHz程度で分解能が確保できるのなら、フィルターからそのままスピンドル入力に入れられないのでしょうか?
10Hzや100HzならPICで処理した方が良いでしょうけど。でもその場合はデジタルで入力した方が面倒じゃないと思います。



MABOさんの方はデジタル入力ですよね。
MACHは実際の回転数を入れると調整してくれるのですか?知らなかったです。
そっちの方の感想も書いておきます。


・割り込みで利用する外部変数にはvolatileを付けておいた方が良い。

・スピンドル停止時の処理はTIMER0を使っているけど、現在の8ms(だと思う)は
 不適当。テスト期間中は0.2sぐらいにしておいた方がMACHを弄りやすい。

※わざわざTIMER0を使わなくても、TIMER2割り込み内で、
 pwmPeriodCounter++;//の後に
 if(pwmPeriodCounter>2000)zero_pwm();
 とか。

・現在、100usでサンプリングしていますけど、総カウント値を読み取った方が良いです。
 勿論、タイマー2はPWMと併用しているのでタイマー2をリセットするわけにはいきません。
 外部割り込み時にタイマー値を保存して、何回回ったかを加味して、算出します。
 ※使っていないタイマー1を利用した方が、タイマー自体をリセットできるので楽。
猛牛ロック   2019/06/02(Sun) 06:03 No.1518
Re: 続続続ーPWM
maboさんへ、
>if(abs((buffer-hozon))>10)

保存した物と現在の値が10以上ひらいたら,

という風に変更したら,まずは,動きました。


ご教授いただいた部分を自分なりに変えました。
8行目です。
でも、まったくモニター用LEDが反応しません。((+_+))


1 // ADコンバータ設定
2 ADCON0 = 0b00100001; // アナログ変換情報(RB4から読込む)
3 ADCON1 = 0b11010000; // 読取値は右寄せ、A/D変換クロックはFOSC/16、VDDをリファレンスとする
4
5 while (1) {
6 hozon = adconv(); // A/D変換対象チャンネルを設定
7 __delay_us(50);
8 if (abs(hozon - adconv())>10) {
9 newhozon = adconv();
10 if (abs(hozon-newhozon)<= 10) {
11 newhozon = hozon;
12 if ((hozon > newhozon)>10) {
13 RA3 = 1;
14 increse((hozon - newhozon) / 10);
15 }
16 if ((newhozon > hozon)>10) {
17 RA3 = 0;
18 increse((newhozon - hozon) / 10);
19 }
20 hozon = newhozon;
21 }
22 }
23 }
24 }
25 //増減をカウント関数
26 void increse(int ohom) {
27 int i;
28 for (i = 0; i < ohom; i++) {
29 RA1 = 0;
30 __delay_ms(100);
31 RA1 = 1;
32 __delay_ms(1000);
33 }
34 }
35
36 // アナログ値の変換と読込み処理関数
37 unsigned int adconv(void) {
38 GO_nDONE = 1; // アナログ値読取り開始指示
39 while (GO_nDONE); // 読取り完了まで待つ
40 return ADRES;
41 }
TR   2019/06/02(Sun) 08:29 No.1519
Re: 続続続ーPWM
猛牛ロックさんへ
レスが遅くなってすみません。

外部変数なんて聞いたことがないので、まったく反応ができません。
それでも、少し見ましたが、断念。
今は、この状態です。

No1518について

このプログラムではADC値(1024分割)が基準になっていて、ワイパー(100分割)の位置が意識されていません。
X9Cは操作は簡単と言えますけど、絶対位置が無いのでワイパー位置は自分で管理する必要があります。
(現在、ポテンショメータの両端を行き来するような動きになると思います)
その辺りは絶対位置で指定できるタイプの方が簡単です。


なるほどなと思います。
具体的には、No1515中にその記載があるのでしょうか?
TR   2019/06/02(Sun) 08:43 No.1520
Re: 続続続ーPWM
外部変数は、関数外に書いてある変数です。グローバル変数と同じです。

> //外部変数
> volatile char x9c_val;

このx9c_valという変数自体がワイパー位置です。X9C VALUE(X9Cの値)です。
どの関数からも操作可能にします。

その次に書いてある

> void x9c_init(void)

これが初期化関数です。
99回ワイパーをダウンさせて確実に0の位置まで移動してx9c_valを0にします。
なので、while(1)の直前に1回実行させます。


> void x9c_up(void)

> void x9c_dowm(void){

名前の通り、UPやDOWNさせる関数です。1つだけ移動させます。
関数内でx9c_valも変化させています。
場合によっては限界位置を超えた操作をしている、という戻り値を付けても良いです。

MABOさんのように複数回上下させる関数も考えましたけど、1つ動かすの500us以上間隔をあける
必要があるらしいので、その手法は止めました。
つまり、数usで新たな値が取得できるのに、500×回数分の時間を割くことも無い、という判断です。
あとはこっちの方がノイズ等に強い=反応が鈍いと思います。

No1518の
> (現在、ポテンショメータの両端を行き来するような動きになると思います)
これは勘違いでした。レンジ自体は/10になっていますね。
使っている内に使用範囲でまとまる気はします。でもちゃんと位置を把握したものにすべきです。


別件ですけど、No1516
> void increse(int ohom){
> int i;
> for(i=0;i<ohom;i++){
> INC=LOW;
> __delay_ms(100);
> INC=HIGHT;
> __delay_ms(1000);
> }

だと、ワイパーを20段階動かすのに22秒かかります。
これはMACHからの信号を受けてのテストですか?それとも可変抵抗でのテスト?
手元の可変抵抗ならいくらなんでも遅すぎかと思います。
ワイパーが移動完了するまでは可変抵抗の変化は受け付けません。
猛牛ロック   2019/06/02(Sun) 11:39 No.1521
Re: 続続続ーPWM
猛牛ロックさんへ

>どの関数からも操作可能にします。


そうか、そういわれて、x9c_val=0とかが見えてきました。
こうして、0点に戻しているわけですよね?



以下のことについても、すみませんが、教えてください。
宜しくお願いします



01 //外部変数 −
02 volatile char x9c_val; −
03 −
04 void x9c_init(void) { − x9c_init関数は、何をしようとしているのですか?
05 ud = 0; −
06 for (char i = 0; i < 99; i++) { −
07 inc = 0; − なぜ、0と1にするのですか?
08 __delay_us(1); −
09 inc = 1; −
10 __delay_us(500); −
11 } −
12 x9c_val = 0; − 0ということは、この時点で、終了ということ?
13 } −
14 −
15 void x9c_up(void) { −
16 ud = 1; −
17 inc = 0; −
18 __delay_us(1); −
19 inc = 1; −
20 if (x9c_val < 99)x9c_val++; −
21 //次の上げ下げは500us空ける −
22 } −
23 −
24 void x9c_dowm(void) { − こ24〜31行目の間は、何をさせているのですか?
25 ud = 0; −
26 inc = 0; −
27 __delay_us(1); −
28 inc = 1; −
29 if (x9c_val > 0)x9c_val--; −
30 //次の上げ下げは500us空ける −
31 } −
32 −
33 void main() { −
34 −
35 //略 −
36 −
37 x9c_init(); −
38 while (1) { −
39 static unsigned int adc[4] = {0}; − adc[4]の意味?
40 static char num = 0; − numの意味?
41 unsigned int target = 0; −
42 adc[(++num)&3] = adconv(); −
43 for (char i = 0; i < 4; i++)target += adc[i]; − targetの意味?
44 target /= 40.9; −
45 −
46 if (target > x9c_val)x9c_up(); −
47 else if (target < x9c_val)x9c_down(); −
48 _delay_ms(1); −
49 } −
50 } −
TR   2019/06/02(Sun) 12:46 No.1522
Re: 続続続ーPWM
> x9c_init関数は、何をしようとしているのですか?
デバイスの初期化です。このデバイスはスタート位置がありません。
(CSピンを操作して起動する位置を決める=保存する事は可能です。)
なので、99回ワイパー位置を下げて、0の位置まで持ってきて、その位置を0にしています。

> 24〜31行目の間は、何をさせているのですか?
x9c_up() →位置を1つ上げる関数
x9c_down()→位置を1つ下げる関数
です。やってる事はudピンを合わせて、クロックを入れています。
ワイパー位置が変化するので、その分、変数x9c_valも操作しています。

> adc[4]の意味?
> numの意味?
やっているのは4回分のADCサンプルを取って処理している、という事です。
デジタルをフィルターを通してアナログ化しているので、多少の波ができます。
4回といわず、倍の8回分位取った方がいいかも。
numはただの数です。回数を数えるために(++num)使っています。

> targetの意味?
ターゲット、目標値です。つまり、MACHからのPWM信号は(100分率で)この値が来ているので、
それになるようにx9cを操作する、という流れです。
猛牛ロック   2019/06/02(Sun) 15:44 No.1523
Re: 続続続ーPWM
猛牛ロックさんへ

7〜9行目は、初期化のために7行目で一旦、0にし、1μs後に1としてHiにしてるのですか?


12行目も初期化の為に、x9c_valに0を代入しているのですか?


adc4は配列関数で、個数が4個あり、{}内に値を書くと思うのですが、0の1個だけでいいのですか?4個分の値を書かなくていいのですか?


44行目の40.9の算出方法を具体的に教えてくださいお願いします。
TR   2019/06/02(Sun) 16:35 No.1524
Re: 続続続ーPWM
> 7〜9行目は、初期化のために7行目で一旦、0にし、1μs後に1としてHiにしてるのですか?

void x9c_init(void) {
ud = 0;
for (char i = 0; i < 99; i++) {
inc = 0;
__delay_us(1);
inc = 1;
__delay_us(500);
}
x9c_val = 0; − 0ということは、この時点で、終了ということ?
}

初期化は、起動時にどの位置にワイパーがあるのか不明なので行います。
今回は普通に、0の位置にワイパーを移動させて初期化します。
Max位置の99まで上げて99に初期化しても良いです。
ワイパー位置を上げる場合は、udピンを1にして、クロック(incピンを↓でストローブ)を入れます。
下げる場合はudピンを0にして、クロックを入れます。
で、今回の目的は99回ワイパーを下げて、0の位置にしたのちに、その位置をx9c_valに記憶させます。

まず、
ud=0;
で下げるむきにしておいて、
for文で99回クロックを入れて、位置を99回下げています。
まぁ、起動時に10の位置で起動したら実際に行われるのは9回までで残り90回は無駄な動作ですけど、
最初の位置が判らないので仕方が無い処理です。
__delay_us(1); や__delay_us(500);はデバイスを動作させるのに必要な間隔です。
それ以上なら問題ありません。

> 12行目も初期化の為に、x9c_valに0を代入しているのですか?
そうです。絶対位置で指定できるデバイスならこれらの処理は必要ありません。

> adc[4]は配列関数で、個数が4個あり、{}内に値を書くと思うのですが
配列の初期化の方法の1つです。その記述ですべて0で初期化されます。


> 44行目の40.9の算出方法を具体的に教えてくださいお願いします。
その前に、adc[4]に入っている過去4回のデータを足しています。
つまり、最大値が1023*4=4092です。これが100分割になるように40.9で割っています。
※今気づきましたけど、最大値が99になるようにすべきですね。
なので、40.93で割った方が良いです。
猛牛ロック   2019/06/02(Sun) 17:33 No.1525
Re: 続続続ーPWM
猛牛ロックさんへ

配列adcの{0}により、43行目の左辺が0(初期化)になるのでしょか?
0になるのは、targetですか?
でも、44行目と意味がつながらない。これでは、おかしいどうして?


42行目は、adcon()関数を実行して、その値をどうしようとしているのですか?[]の意味が分かりません??
察するに、46行目で、adc変換後の値(4回分の合計値)を40.9で割って、
出た値とx9c_valをif文の中でxpcをup/downの関数を呼び出しているわけでしょうか?
それとですが、
以下のように、adconv()関数をmain関数の後につけましたが、どうもうまくつながりません。どうしたらよいでしょうか?

// アナログ値の変換と読込み処理関数
unsigned int adconv() {
unsigned int temp;
GO_nDONE = 1; // アナログ値読取り開始指示
while (GO_nDONE); // 読取り完了まで待つ
temp = ADRESH; //
temp = (temp << 8) + ADRESL; //RA0で読み込んだ値をtempに代入
return temp; //読み込んだtempをnumに返す
TR   2019/06/02(Sun) 18:50 No.1526
Re: 続続続ーPWM
TRさん,猛牛ロックさん,こんばんは。

横レスになってしまいますが,ご容赦を・・・・。


*********猛牛ロックさんへ*********
ーーー基本周波数の変更のプログラムについてーーーー
感想ありがとうございます。
このプログラムは,諸兄のプログラムを移植したもので,
オリジナルは私ではないので,理解するのに苦労しました。
ご指摘のように,TIMER0で,最初,8msで,
停止の処理してましたが,読み込む周波数が100hzで,
取りこぼしてたので,現在は,倍の16msにしたと思います。
サンプリングの方法については,いじると全体が,
おかしくなる可能性あるので,いじっていません。
オリジナルでないので,あまりいじりたくないなと,思ってます。

>MABOさんの方はデジタル入力ですよね。
>MACHは実際の回転数を入れると調整してくれるのですか?知らなかったです。
>そっちの方の感想も書いておきます。
デジタル入力ですが,デジタルポテンショメータも興味あって,弄り始めました。
MACHには,クローズドループ,ループバック等の設定もあります。
PIDの数値の入力もありますが,ここは,ちょっと分かりません。
チェックの有無で,私の環境では,大きな変化ありませんでした。
設定がまずいのかも。

−−−−−1516のプログラムについてーーーー
void increse(int ohom){
int i;
for(i=0;i<ohom;i++){
INC=LOW;
__delay_ms(100);
INC=HIGHT;
__delay_ms(1000);
}

ですが,これ,LEDの点滅で動作確認のため遅くしました。
実機がないので,こんなことで,目視で確認してます。

−−−−−デジタルポテンショメーターについてーーーー
初期化のことについては,猛牛ロックさんのおっしゃる通りだと思います。
ただ,途中のワイパーの動きをを保持(記憶)しなければ,
デフォルトに戻るのかな,なんて思ってました。
マニュアルから,デフォルトの設定読み取れなかったので,
もしかして,ワイパーは,10kΩだと40Ωのところがデフォルトかな,と邪推してました。
それから,ワイパーは,99じゃなくて,最大動けるのは,
98かもですね。
不確かですが,最大動かしても,「40Ω残る」 の記事が,
マニュアルにあったような。
一番端までは,いけないような気がします。

*****TRさんへ******
混乱すると申し訳ないので,
猛牛ロックさんの書いてくれたプログラムについては,
控えたいと思いますが,
下記のこと分かると,理解しやすいと思います。

 A+=A
は,
 A=A+1
と同じ意味で,表記方法が違うだけです。
私はこの書き方は苦手です。
http://www1.cts.ne.jp/~clab/hsample/Primary/Io11.html

それと,是非,LCD導入なさることおすすめします。
格段にデバックの効率あがります。
LCDの表示は,通常のものであれば,
それほど難しくはないと思います。
選ぶときは,インターフェースが,I2C以外のものの
方がと思います。

http://akizukidenshi.com/catalog/g/gP-00038/
あたりでしょうか。
mabo   2019/06/02(Sun) 22:02 No.1527

処理 記事No 暗証キー

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