製作モジュール一覧

ラベル DAC の投稿を表示しています。 すべての投稿を表示
ラベル DAC の投稿を表示しています。 すべての投稿を表示

2019年4月2日火曜日

STM32: 内蔵DACをDMA経由で使う(Nucleo-F446RE)

内蔵DACをDMA経由で使ってみました。データをあらかじめ用意できれば、DMAにデータ転送をまかせて、CPUは他の処理が行えます。

参考
「Elastic Notes」さんの「Usage DMA and DAC in STM32CubeMX

プロジェクト
https://github.com/ryood/STM32Cube_Test/tree/master/SW4STM32/Nucleo-F446_DAC_DMA_Test2

実行環境

  • Nucleo-F446RE
  • STM32CubeMX Version 5.1.0
  • System Workbench for STM32 - C/C++ Embedded Development Tools for MCU Version: 2.8.1.201903050911

4096サンプルのサイン波テーブルを作成して内蔵DACから出力します。

STM32CubeMXの設定


Clock Configuration
  PLL Source Mux: HSE
  HCLK: 180MHz

Pinout & Configuration
  Timers
    TIM6
      Mode: Activatedをチェック
      Counter Period: 220
      Trigger Event Selection: Update Event

180MHz駆動するとAPB1 Timer clocksは90MHzになります。4096サンプルで1波形のサイン波を出力するので、1kHzのサイン波を出力しようとすると
90MHz / prescaler / 4096 = 1kHz
なので
prescaler = 90MHz / (1kHz * 4096) ≒ 22.0
ですが、prescalerを22に設定するとDACから信号が出力されませんでした。100Hzにしようとprescalerを220に設定するとOKでした。

  Analog
    DAC
      Mode: OUT1 Configurationをチェック
      Prameter Settings
        Trigger: Timer 6 Trigger Out event
      NVIC Settings
        Enableをチェック
      DMA Settings
        DMA Request: DAC1を追加
        Mode: Circular
        Increment Address: Memory
        Data Width: Half Word
     

 SW4STM32でコードを追加(一部抜粋)


/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <math.h>
/* USER CODE END Includes */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define SINE_TABLE_SIZE (4096)
/* USER CODE END PD */

/* USER CODE BEGIN PV */
uint16_t sine_wave_array[SINE_TABLE_SIZE];
/* USER CODE END PV */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static void generateSineWave(void)
{
  for (int i = 0; i < SINE_TABLE_SIZE; i++) {
      float fv = ((float)i / SINE_TABLE_SIZE) * 2.0f - 1.0f;
      float phi = (float)M_PI * fv;
      sine_wave_array[i] = 4095 * ((sinf(phi) + 1.0f) / 2.0f);
  }
}
/* USER CODE END 0 */

  /* USER CODE BEGIN 2 */
  generateSineWave();
  HAL_TIM_Base_Start(&htim6);
  HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)sine_wave_array, SINE_TABLE_SIZE, DAC_ALIGN_12B_R);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

Memory→DACのデーター転送はTimer駆動(TIM6)のDMAにまかせているので、プログラム(while(1)ループ)では何もしていません。

出力波形

いつものように、サイン波形の最大振幅付近で若干クリップしています。

99.6Hzのサイン波になりました。水晶がクロック源なので少し誤差が大きいような・・・(@@?

Prescaler Prescler(丸め) 誤差
219.7265625 220 0.1244%

期待周期(ms) 実測周期(ms) 誤差
10 10.04 0.4000%

2019年3月30日土曜日

STM32: 内蔵DACを使う(Nucleo-F446RE)

Nucleo-F446REの内蔵DACからSIN波を出力しました。

参考
<STM32Cube>\Repository\STM32Cube_FW_F4_V1.24.0\Projects\STM32446E_EVAL\Examples\DAC\DAC_SimpleConversion

プロジェクト
https://github.com/ryood/STM32Cube_Test/tree/master/SW4STM32/Nucleo-F446_DAC_Test5

実行環境

  • Nucleo-F446RE
  • STM32CubeMX Version 5.1.0
  • System Workbench for STM32 - C/C++ Embedded Development Tools for MCU Version: 2.8.1.201903050911

STM32CubeMXの設定



STM32CubeMXに[Report]という機能があったので出力してみました。

https://github.com/ryood/STM32Cube_Test/blob/master/SW4STM32/Nucleo-F446_DAC_Test5/Nucleo-F446_DAC_Test5.pdf

SW4STM32でコードを追加(一部抜粋)

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <math.h>
/* USER CODE END Includes */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  double phi = 0.0;
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    uint16_t sinv = 4095 * ((sin(phi) + 1.0) / 2.0);
    if (HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, sinv) != HAL_OK)
    {
      Error_Handler();
    }
    if (HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, sinv) != HAL_OK)
    {
      Error_Handler();
    }
    phi += 0.01;
  }
  /* USER CODE END 3 */
}

位相角を0.01ずつ増やしてsinの値を求め、12bit値に変換して2chある内蔵DACから出力しています。

出力結果


ch1:DAC1(PA4) ch2:DAC2(PA5)

DAC2はNucleoボード上でLEDに接続されているため、上側がクリップしています。DAC1も上下の最大振幅付近で若干クリップしています。

2017年1月9日月曜日

Nucleo F446RE 内蔵DACのテスト

Nucleo F446REを仕入れたのでテストしてみた。F401REのパワーアップ版という感じで、駆動クロックが180MHzになっている(F401REは84MHz)。またDACが内蔵されているのでmbedのAnalogOutが使える。

mbedのオンライン・コンパイラでPlatformにNucleo F446REを選ぶとDACを使ったテンプレートが選択できるようになる。「Outoput a sinewave using DAC.」というテンプレートをもとにテストしてみた。



#include "mbed.h"

AnalogOut my_output1(PA_4);
AnalogOut my_output2(PA_5);

#define PI        (3.141592653589793238462)
//#define AMPLITUDE (1.0)    // x * 3.3V
#define AMPLITUDE (0.8)    // x * 3.3V
#define PHASE     (PI * 1) // 2*pi is one period
#define RANGE     (0x7FFF)
#define OFFSET    (0x7FFF)

// Configuration for sinewave output
#define BUFFER_SIZE (360)
uint16_t buffer[BUFFER_SIZE];

void calculate_sinewave(void);

int main() {
    printf("Sinewave example\n");
    calculate_sinewave();
    while(1) {     
        // sinewave output
        for (int i = 0; i < BUFFER_SIZE; i++) {
            my_output1.write_u16(buffer[i]);
            my_output2.write_u16(buffer[i]);
            //wait_us(10);
        }
    }
}

// Create the sinewave buffer
void calculate_sinewave(void){
  for (int i = 0; i < BUFFER_SIZE; i++) {
     double rads = (PI * i)/180.0; // Convert degree in radian
     buffer[i] = (uint16_t)(AMPLITUDE * (RANGE * (cos(rads + PHASE))) + OFFSET);
  }
}


bufferにサインテーブルを作って、メインループでDACからサイン波を出力するというもの。F446REでDAC出力として選択できるPinは

DAC1: PA_4
DAC2: PA_5

で両方同時に使えた。

Amplitudeを1.0にしてPA_4から出力


ch1:PA_4

約6.4kHzで出力できているが、サイン波の上下で波形がつぶれて歪んでいる。

BUFFER_SIZEが360なので、6.4kHzのサイン波が出力できているということはサンプリング・レートは約2.3MHz(434ns)で、mbedで使った場合このあたりが上限。


Amplitudeを0.9にしてPA_4から出力



ch1:PA_4

Amplitudeを0.9にして出力すると歪はほとんどなくなった。解像度はわるくなるが、レール電圧付近は使わない方が良さそう。


Amplitudeを0.9にしてPA_4とPA_5から出力




ch1:PA_4 ch_2:PA_5

2つのDACから同時に波形を出力できたが、Amplitudeを0.9にしてもPA_5の方の上がつぶれてしまった。PA_5はNucleoボード上でLEDがつながっているのでこれが影響してるのかも?出力電圧が上がった時に、LEDに電流がとられて電圧を十分にスイングできていない可能性がある。

また、2つのDAC同時に出力するとサイン波の周波数が約3.3kHzに低下。1つだけ使った場合のおおよそ1/2なので、DAC1とDAC2はインターリーブなのかも。


Amplitudeを0.9にしてPA_5単体で出力



ch2:PA_5

PA_5単体で出力しても同様。周波数は約6.4kHzに上がっている。


Amplitudeを0.8にしてPA_5単体で出力



ch2:PA_5

振幅の最大値が3V程度になるようにAmplitudeを0.8にすると波形の歪は改善される。

2016年7月4日月曜日

R-2RラダーDACのシミュレーション

Google+の電子工作部で以前R-2RラダーというDAコンバートの回路を教えてもらったのでシミュレーションしてみた。

スイッチを並べた鍵盤からアナログ値を取り出すような用途を想定。

またR-2Rラダーの回路には電圧出力型と電流出力型があるようだ。

電圧出力型

回路図

LTSpiceのswコンポーネントは単投しか使えないので、ノーマルONとノーマルOFFの2つのswを並列にして双投として使った。(この使い方もGoogle+で教えてもらいました。感謝です(^q^/)
.model SW1 SW(Ron=1 Roff=10Meg Vt=1)
.model SW2 SW(Ron=10Meg Roff=1 Vt=1)
として、SW1がノーマルOFF、SW2がノーマルONになるようにした。Ron/Roffの値は0が指定できないので1Ω。(デフォルトでも1Ωになっているようだ)

S1/S2などの組み合わせが単極双投のスイッチになる。スイッチを押したらVCC、離したらGNDに繋がるようなイメージ。

V2~V5で周期の違う矩形波を出力して4bit相当の組み合わせを作った。

過渡解析

一番下のV(out)が出力電圧。

最大値は10Vではなく9.375V。いちいち抵抗の分圧を計算していくのはめんどくさいが、4bitなら2^4=16なので
Vcc * (15 / 16)
で求まる。

電流出力型

回路図

電流出力型の回路もGoogle+で教えてもらった。電圧出力型と似てるが微妙に違う。出力は電流なのでRconv=1kΩに流してシミュレーションした。

過渡解析

一番下のI(Rconv)が出力電流。

電流は各bitごとに1/2されていくのでVCCから流れ出す電流をIとするとR1にI/2、R3にはI/4、R5にはI/8、R7とR2にはI/16というふうに電流が流れる。(Rconvは無視)
I = 2 * (VCC / R1) =  2 * (10V / 100kΩ) = 200uA
スイッチがすべてOnのとき、Rconvに流れ込む電流Irconvは、R2に流れ込む電流をIr2とすると

Irconv = I - Ir2 = 200uA - (200uA * (1 / 16)) = 187.5uA

Rconv自体に抵抗があるのでシミュレーションでは少し減っている。