• 正文
  • 相关推荐
申请入驻 产业图谱

AD5933阻抗测量芯片(6):基于MCP4017的自动切换量程阻抗测量实现

5小时前
234
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

上一期我们介绍到使用AD5933实现对阻抗器件进行扫频得到器件阻抗曲线并显示到OLED显示屏上:

但是在这个板子的设计中,AD5933的反馈电阻是由数字电位器MCP4017来决定的:

在实际的使用中使用了MCP4017-104,最大电阻100K,即AD5933的反馈电阻最大100K。这个反馈电阻直接决定了AD5933的可测量阻抗范围。

因此本期我们在上一期的基础上,实现AD5933的自动化切换量程实现。

680K电阻

470K电阻

4.9K电阻

1000K电阻

1、代码实现

while (1){     float sweep_ohm[80];     float log_ratio = 1.0f;     uint8_t sorted_indices[80];     uint8_t median_index = 0;
     if (kSweepPoints > 1)     {       log_ratio = powf(kSweepEndHz / kSweepStartHz, 1.0f / (kSweepPoints - 1));     }
     for (uint8_t i = 0; i < kSweepPoints; i++)     {       float current_freq = kSweepStartHz * powf(log_ratio, i);              AD5933SetDDS(current_freq);       AD5933Start(StartSweep);       AD5933GetALL(Repeat);              sweep_ohm[i] = ad5933data.R;              ad5933data.SweepData[i].Frequency = current_freq;       ad5933data.SweepData[i].Real = ad5933data.Real;       ad5933data.SweepData[i].Imag = ad5933data.Imag;       ad5933data.SweepData[i].R = ad5933data.R;       sorted_indices[i] = i;     }
     for (uint8_t i = 0; i < kSweepPoints - 1; i++)     {       for (uint8_t j = i + 1; j < kSweepPoints; j++)       {         if (sweep_ohm[sorted_indices[i]] > sweep_ohm[sorted_indices[j]])         {           uint8_t temp = sorted_indices[i];           sorted_indices[i] = sorted_indices[j];           sorted_indices[j] = temp;         }       }     }     median_index = sorted_indices[kSweepPoints / 2];     float median_impedance = ad5933data.SweepData[median_index].R;     float actual_rfb = (float)RfbLevels[RfbIndex] * (MCP4017_TOTAL_RES / MCP4017_STEPS);     float min_measure_range = actual_rfb;     float max_measure_range = actual_rfb * 10.0f;     uint8_t need_rescan = 0;     if (median_impedance > max_measure_range && RfbIndex < kRfbLevels - 1)     {       RfbIndex++;       need_rescan = 1;     }     elseif (median_impedance < min_measure_range && RfbIndex > 0)     {       RfbIndex--;       need_rescan = 1;     }     if (need_rescan)     {       Rfb = RfbLevels[RfbIndex];       MCP4017_SetWiper(Rfb);       ad5933data.Rfb = Rfb;       for (uint8_t i = 0; i < kSweepPoints; i++)       {         float current_freq = kSweepStartHz * powf(log_ratio, i);         AD5933SetDDS(current_freq);         AD5933Start(StartSweep);         AD5933GetALL(Repeat);         sweep_ohm[i] = ad5933data.R;         ad5933data.SweepData[i].Frequency = current_freq;         ad5933data.SweepData[i].Real = ad5933data.Real;         ad5933data.SweepData[i].Imag = ad5933data.Imag;         ad5933data.SweepData[i].R = ad5933data.R;         sorted_indices[i] = i;       }       for (uint8_t i = 0; i < kSweepPoints - 1; i++)       {         for (uint8_t j = i + 1; j < kSweepPoints; j++)         {           if (sweep_ohm[sorted_indices[i]] > sweep_ohm[sorted_indices[j]])           {             uint8_t temp = sorted_indices[i];             sorted_indices[i] = sorted_indices[j];             sorted_indices[j] = temp;           }         }       }       median_index = sorted_indices[kSweepPoints / 2];     }     ad5933data.SweepPointCount = kSweepPoints;     ad5933data.MaxImpedanceIndex = median_index;     ad5933data.Frequent = ad5933data.SweepData[median_index].Frequency;     ad5933data.Real = ad5933data.SweepData[median_index].Real;     ad5933data.Imag = ad5933data.SweepData[median_index].Imag;     ad5933data.R = ad5933data.SweepData[median_index].R;     UpdateSweepGraph(sweep_ohm, kSweepPoints, kSweepStartHz, kSweepEndHz);     u8g2_FirstPage(&u8g2);       do       {         MainGUI(&u8g2);       } while (u8g2_NextPage(&u8g2));    /* USER CODE END WHILE */    /* USER CODE BEGIN 3 */  }

第一步,系统上电后,从7个预设档位中取第3档作为初始值。档位表是{5, 20, 35, 50, 65, 80, 100},这些数字是 MCP4017 数字电位器的抽头值,范围0到127。数字电位器总阻值是100kΩ,所以实际反馈电阻=抽头值 × (100kΩ / 127),初始档位35对应实际电阻约 27.6kΩ。

第二步,每轮主循环先做一次完整的80点对数扫频,频率从6kHz 覆盖到100kHz。每个频点调用AD5933GetALL 做3次采样取平均,得到阻抗值,存入sweep_ohm数组和 ad5933data.SweepData结构体中。

第三步,用冒泡排序对80个阻抗值从小到大排序,取出中位数。用中位数而不是平均值是为了避免个别频点的极端数值干扰判断。

第四步,根据当前实际反馈电阻值计算有效测量范围。下限=actual_rfb,上限=actual_rfb × 10。这是AD5933的特性决定的:反馈电阻决定了测量灵敏度,被测阻抗在Rfb到Rfb×10范围内时精度最好。

第五步,比较中位数阻抗和当前测量范围。如果中位数大于上限,且当前不是最高档,就把RfbInde 加 1,切换到更大的反馈电阻。如果中位数小于下限,且当前不是最低档,就把RfbIndex减 1,切换到更小的反馈电阻。如果不需要切换,就跳过重扫。

第六步,如果发生了档位切换,用新抽头值重新配置 MCP4017和ad5933data.Rfb,然后重新执行一遍完整的 80 点扫频,再排序取中位数。注意这里只重扫一次,如果重扫后仍然不在范围内,不会继续递归切档,要等到下一轮主循环。

第七步,把中位数对应的频率、实部、虚部、阻抗写入 ad5933data的显示字段,把80点数据传给 UpdateSweepGraph画曲线图,最后刷新OLED。

AD5933在0.8Rfb-10Rfb范围内都可以呈现线性范围,在这个范围之外精度就会呈现非线性。

Rfb改变时,这条直线的系数会发生改变,每个Rfb对应的直线系数P也是呈线性关系的

floatGetR(float Rfb, float Z){  float P1 = 7428.0f * Rfb + 3580.0f;  float R = P1 * Z;  return R;}

因此可以实现在不同Rfb的情况下也可以精确的计算AD5933所测量的真实阻抗。

相关推荐