thunderbolt!

thunderbolt!

PR

×

カレンダー

キーワードサーチ

▼キーワード検索

2026.04.10
XML
テーマ: 私のPC生活(7586)
カテゴリ: PC関係
昨日の続き。
Arduino+MCP4922+LM358でPC制御できる0-10V電源(6系統)を作っています。
ハードウェアとArduinoのスケッチが出来たので、動作確認してみます。

シリアルモニタで1A_4095と送れば、フルパワー(MCP4922で5V、増幅して10V)が出るはず。
なんですが、実際やってみると4095送ってもMCP4922で4.4Vにしかなりません。
​
デュアル 12ビット DAコンバータ シリアル (SPI / マイクロワイヤ) 14ピン PDIP 1袋 (2個入) MCP4922-E/P ​
これは、私の環境ではMCP4922の基準電圧(Vref)に4.4Vしかかかってないからです。

MCP4922のVrefはArduinoの5V出力から取っていますが、これは様々な理由で電圧が落ちるらしい。

​
【送料無料】安定化電源 AC 100-240V to DC 5V コンバーター スイッチング電源 直流電源変換器 短絡・過負荷・過電圧保護機能 アルミ製 サイズ:5A 25W ​


上限ぎりぎりの5V近い電圧が必要ならそれも仕方ないですが、余裕があるならArduinoで電源電圧(Vcc)を読んで補正してやれば(落ちる分を見越して大き目の電圧を出力指示すれば)それで済みます。
Arduinoに直接Vcc電圧を取得するコマンドはないですが、うまくコードを書けば配線不要で読めるらしい。
http://radiopench.blog96.fc2.com/blog-entry-490.html


上記を参考に改変したArdinoスケッチがこれ。
送るのは4095までの整数値ではなく、0~5Vまでの電圧そのものを送出することにしました。
ついでにコマンドを拡充し、Rを送出するとVccの電圧を返すようにしました。





#include "pins_arduino.h"
#include <SPI.h>


#define LDAC 9 // ラッチ動作出力ピン
#define MCP1 4 // MCP1選択ピン
#define MCP2 3 // MCP2選択ピン
// MCP3選択ピン

const int Vin_PIN = A0;

void setup () {
Serial. begin (9600);

// 制御するピンは全て出力に設定する
pinMode(LDAC,OUTPUT) ;

pinMode(MCP2,OUTPUT) ;
pinMode(MCP3,OUTPUT) ;

//最初はすべてhighにする
digitalWrite (MCP1,HIGH) ;
digitalWrite (MCP2,HIGH) ;
digitalWrite (MCP3,HIGH) ;

// SPIの初期化処理を行う
SPI.begin() ; // SPIを行う為の初期化
SPI.setBitOrder(MSBFIRST) ; // ビットオーダー
SPI.setClockDivider(SPI_CLOCK_DIV8) ; // クロック(CLK)をシステムクロックの1/8で使用(16MHz/8)
SPI.setDataMode(SPI_MODE0) ; // クロック極性0(LOW) クロック位相0

//電源電圧測定
pinMode(14, OUTPUT);

}



void loop () {

//シリアルポートを読んで有効な文字があったら

while(Serial.available()>0){

String cmds = Serial. readStringUntil ('\n');
String MCPnumber = cmds.substring(0,1);
String MCPport=cmds.substring(1,2);
float vValue = cmds.substring(3).toFloat();

float Vcc = cpuVcc(); // 電源電圧測定
int iValue = vValue / Vcc * 4095; //電圧を整数値に変換
if(iValue>4096) {iValue=4095;} / /上限を4095でクリップ


//CSを選択
if(MCPnumber =="R"){
Serial. println (Vcc,2); // シリアルポートにVccを書き出す
delay(200);
break;

}else if(MCPnumber =="1"){
digitalWrite (MCP1,LOW) ;

}else if(MCPnumber =="2"){
digitalWrite (MCP2,LOW) ;

}else if(MCPnumber =="3"){
digitalWrite (MCP3,LOW) ;
}

//ポートを選択
int PortOfset;
if(MCPport =="A"){
PortOfset=B00110000;

}else if(MCPport =="B"){
PortOfset=B10110000;
}

//出力
digitalWrite (LDAC,HIGH) ; //LDACを上げる
SPI.transfer(((iValue >> 8) & 0x0F) | PortOfset) ; // Highバイト(0x30=OUTA/BUFなし/1x/シャットダウンなし)
SPI.transfer(iValue & 0xff) ; // Lowバイトの出力 上位バイトを消す

//CSを戻す

digitalWrite (MCP1,HIGH) ;
digitalWrite (MCP2,HIGH) ;
digitalWrite (MCP3,HIGH) ;

// ラッチ信号を出す(出力指示)

digitalWrite(LDAC,LOW) ;
}

}

float cpuVcc(){ // 電源電圧(AVCC)測定関数  Vref=AVcc, input=internal1.1V
long sum=0;
ADMUX = 0x4E; // ADC Multiplexer Select Reg.
ADCSRA |= ( 1 << ADEN); // ADC イネーブル
ADCSRA |= 0x07; // AD変換クロック CK/128
delay(10);

for(int n=0; n < 10; n++){
sum = sum + adc(); // adcの値を読んで積分
}
return (1.1 * 10240.0)/ sum; // 電圧を計算して戻り値にする
}

unsigned int adc(){ // ADCの値を読む
unsigned int dL, dH;
ADCSRA |= ( 1 << ADSC); // AD変換開始
while(ADCSRA & ( 1 << ADSC) ){ // 変換完了待ち
}
dL = ADCL; // LSB側読み出し
dH = ADCH; // MSB側
return dL | (dH << 8); // 10ビットに合成した値を返す
}







これでVccの値を気にせず、どのような環境でもぴったりの電圧が出力されるようになります。


明日に続く。











お気に入りの記事を「いいね!」で応援しよう

最終更新日  2026.04.21 23:07:29
コメント(0) | コメントを書く


■コメント

お名前
タイトル
メッセージ
画像認証
上の画像で表示されている数字を入力して下さい。


利用規約 に同意してコメントを
※コメントに関するよくある質問は、 こちら をご確認ください。


【毎日開催】
15記事にいいね!で1ポイント
10秒滞在
いいね! -- / --
おめでとうございます!
ミッションを達成しました。
※「ポイントを獲得する」ボタンを押すと広告が表示されます。
x
X

コメント新着

quanta511 @ Re[1]:柿の種も高級品になるのか(11/20) まーっさんへ コメントありがとうござい…
まーっ@ Re:柿の種も高級品になるのか(11/20) 更新を楽しみに拝見してます。 古い記事へ…
私はイスラム教徒です@ Re:美大あるある 工学部も同じ(05/07) 神神は言った: コーランで 『 (21) 人…
聖書預言@ Re:どんど焼き(01/14) 神の御子イエス・キリストを信じる者は永…
aki@ この様な書き込み大変失礼致します 日本も当事国となる台湾有事を前に反日メ…

© Rakuten Group, Inc.

Design a Mobile Site
スマートフォン版を閲覧 | PC版を閲覧
Share by: