DAC0808 不想转模拟
DAC0808 doesn't want tranfer to analog
我的讲座给了我们 DAC 实验室。他要求从 Arduino 制作一个 8 位的锯齿波,然后将其连接到 DAC0808 以通过放大器产生模拟信号。所以我们做了一个电路。检查了它。有用。然后开始做计算和预期的结果。我们已经做到了。最后我们用接线语言编写程序。我想更进一步,制作了一个程序,它接受来自串行的不同输入并改变波形类型。但是当我们出于某种原因试图检查工作电路时它不想工作。我检查了 8 个 LED 上的程序,它们都工作得很好。但是我们把我的 ecircuit 放在示波器上,当它应该有 0 或 5 伏时,它显示 9.7 伏。这些位仍然进入 DAC 输入,但 DAC 没有将它们转换为模拟输出。
讲师确定问题出在我的复杂问题上,而不是我的电路或处理器上,但我注意到非常奇怪的电压输出。当我用万用表触摸 DAC 上的高输入电压时,它会给出该值。他仍然认为代码有问题,因为他的简单版本有效。 :c
- 如果是,我想知道在哪里?
- 或者为什么我不这样做?
代码:
//Global Variables
enum wave {SAWTOOTH = 49, TRIANGLE, SQUARE, SINE, TANGENT};
int incomingByte;
int lastState = 0;
int calcResult;
int binaryOutput;
int triangleCheck;
int squareCheck;
int squareCount;
int sineOutput;
int tangentOutput;
int pin[8];
//Prototypes
int bitConversion(int);
//Setup
void setup() {
Serial.begin(250000);
for (int i = 2; i < 10; i++)
{
pinMode(i, OUTPUT);
pin[i - 2] = i;
}
}
void loop() {
if (Serial.available())
incomingByte = (int)Serial.read();
Serial.print("Incoming Byte: ");
Serial.write(incomingByte);
Serial.println();
Serial.print("Last State: ");
Serial.write(lastState);
Serial.println();
if (incomingByte != lastState)
{
lastState = incomingByte;
calcResult = 0;
triangleCheck = 0;
squareCheck = 0;
squareCount = 0;
sineOutput = 0;
tangentOutput = 0;
Serial.println("State changed!");
}
Serial.print("STATE: ");
switch (lastState)
{
case (SAWTOOTH):
Serial.println("SAWTOOTH WAVE");
Serial.println("------------------------------------------");
if (calcResult == 255)
calcResult = 0;
calcResult++;
break;
case (TRIANGLE):
Serial.println("TRIANGLE WAVE");
Serial.println("------------------------------------------");
if (calcResult == 255 || !calcResult)
{
Serial.println("Triangle changed!");
Serial.println();
triangleCheck++;
}
if ((triangleCheck % 2))
{
Serial.print("ODD ");
calcResult++;
}
else
{
Serial.print("EVEN ");
calcResult--;
}
break;
case (SQUARE):
Serial.println("SQUARE WAVE");
Serial.println("------------------------------------------");
if (squareCount == 255 || squareCount == 0)
{
Serial.println("Square changed!");
Serial.println();
squareCheck++;
}
if ((squareCheck % 2))
{
Serial.print("ODD ");
calcResult = 0;
squareCount++;
}
else
{
Serial.print("EVEN ");
calcResult = 255;
squareCount--;
}
break;
case (SINE):
Serial.println("SINE WAVE");
Serial.println("------------------------------------------");
calcResult = 128+128*sin(2*PI*100*(sineOutput/10000.0));
sineOutput++;
break;
case(TANGENT):
Serial.println("TANGENT WAVE");
Serial.println("------------------------------------------");
calcResult = 128+64*tan(2*PI*100*(tangentOutput/10000.0));
tangentOutput++;
break;
default:
Serial.println("DEFAULT");
Serial.println("------------------------------------------");
calcResult = 0;
break;
}
binaryOutput=calcResult;
Serial.print("Binary Output: ");
Serial.println(binaryOutput, DEC);
if (binaryOutput)
{
for (int i = 7; i >= 0; i--)
{
if (binaryOutput >= bitConversion(i))
{
digitalWrite(pin[i], HIGH);
binaryOutput -= bitConversion(i);
Serial.print(1);
Serial.print(" ");
}
else
{
digitalWrite(pin[i], LOW);
Serial.print(0);
Serial.print(" ");
}
}
}
else
{
for (int i = 7; i >= 0; i--)
{
pinMode(pin[i], LOW);
Serial.print(0);
Serial.print(" ");
}
}
Serial.println("\n\n");
delay(50);
}
int bitConversion(int n)
{
int result = 1;
for (int i = 0; i<n; i++)
result *= 2;
return result;
}
关于您项目的一些事情
对于波形发生器,在主循环中生成信号不是一个好主意。正确的方法是使用定时器和计数器(必要时可以中断)。这是因为在数字信号发生器中,采样频率和波形频率很重要,而在主回路中生成波形可能会产生延迟,从而改变频率。使用计数器,您还可以控制输出信号的频率。
顺便说一下,您可以按照自己的方式进行操作,但正如我所说,它有其局限性。
因为您使用 8 位作为输出并且用 calcResult
变量表示,也许您可以考虑将其设为 byte
或 unsigned char
(两者基本相同)
在正弦波的 calcResult
计算中,它说 calcResult = 128+128*sin(2*PI*100*(sineOutput/10000.0))
但它应该是 calcResult = 128+127*sin(2*PI*100*(sineOutput/10000.0))
因为其他方式你将有 calcResult=256
有时。
变量triangleCheck
一直在增加,这会导致你溢出。尽管这也可以为您提供正确的行为,但使用取值 0 和 1 的布尔值或字符是更好的方法。 squareCheck
.
也会发生这种情况
您似乎在主循环的所有迭代中打印有关 incomingByte 的文本,我认为这可能很烦人(并且还占用处理能力)。
看一下切线波,我在正弦波中提到的溢出也有同样的问题。您应该使用信号的周期性来执行此操作。您还应该考虑到切线是一个无界函数,因此它的值将超过您的 DAC 接受的 255。
对于你在最后一部分做的位转换,也许你可以用位掩码来完成。这样会更干净,更容易处理。
如果您不确定自己的 DAC,可以使用拨码开关进行测试。或者,如果可能的话,使用信号发生器,然后是 ADC,然后是 DAC,最后是示波器。这样您将 100% 确定您的 DAC 正在工作。
你测试过Arduino的输出了吗?您可以将带有电阻的 LED 连接到输出引脚,使用方波信号您应该会看到一些非常清晰的行为。
对于正弦波和正切波我建议看一下变量的转换(float to int)。也许关于它是如何完成的没有问题,但是确定您正在处理的信息是很好的。
希望这至少能对您的项目有所帮助。
您好!
我的讲座给了我们 DAC 实验室。他要求从 Arduino 制作一个 8 位的锯齿波,然后将其连接到 DAC0808 以通过放大器产生模拟信号。所以我们做了一个电路。检查了它。有用。然后开始做计算和预期的结果。我们已经做到了。最后我们用接线语言编写程序。我想更进一步,制作了一个程序,它接受来自串行的不同输入并改变波形类型。但是当我们出于某种原因试图检查工作电路时它不想工作。我检查了 8 个 LED 上的程序,它们都工作得很好。但是我们把我的 ecircuit 放在示波器上,当它应该有 0 或 5 伏时,它显示 9.7 伏。这些位仍然进入 DAC 输入,但 DAC 没有将它们转换为模拟输出。
讲师确定问题出在我的复杂问题上,而不是我的电路或处理器上,但我注意到非常奇怪的电压输出。当我用万用表触摸 DAC 上的高输入电压时,它会给出该值。他仍然认为代码有问题,因为他的简单版本有效。 :c
- 如果是,我想知道在哪里?
- 或者为什么我不这样做?
代码:
//Global Variables
enum wave {SAWTOOTH = 49, TRIANGLE, SQUARE, SINE, TANGENT};
int incomingByte;
int lastState = 0;
int calcResult;
int binaryOutput;
int triangleCheck;
int squareCheck;
int squareCount;
int sineOutput;
int tangentOutput;
int pin[8];
//Prototypes
int bitConversion(int);
//Setup
void setup() {
Serial.begin(250000);
for (int i = 2; i < 10; i++)
{
pinMode(i, OUTPUT);
pin[i - 2] = i;
}
}
void loop() {
if (Serial.available())
incomingByte = (int)Serial.read();
Serial.print("Incoming Byte: ");
Serial.write(incomingByte);
Serial.println();
Serial.print("Last State: ");
Serial.write(lastState);
Serial.println();
if (incomingByte != lastState)
{
lastState = incomingByte;
calcResult = 0;
triangleCheck = 0;
squareCheck = 0;
squareCount = 0;
sineOutput = 0;
tangentOutput = 0;
Serial.println("State changed!");
}
Serial.print("STATE: ");
switch (lastState)
{
case (SAWTOOTH):
Serial.println("SAWTOOTH WAVE");
Serial.println("------------------------------------------");
if (calcResult == 255)
calcResult = 0;
calcResult++;
break;
case (TRIANGLE):
Serial.println("TRIANGLE WAVE");
Serial.println("------------------------------------------");
if (calcResult == 255 || !calcResult)
{
Serial.println("Triangle changed!");
Serial.println();
triangleCheck++;
}
if ((triangleCheck % 2))
{
Serial.print("ODD ");
calcResult++;
}
else
{
Serial.print("EVEN ");
calcResult--;
}
break;
case (SQUARE):
Serial.println("SQUARE WAVE");
Serial.println("------------------------------------------");
if (squareCount == 255 || squareCount == 0)
{
Serial.println("Square changed!");
Serial.println();
squareCheck++;
}
if ((squareCheck % 2))
{
Serial.print("ODD ");
calcResult = 0;
squareCount++;
}
else
{
Serial.print("EVEN ");
calcResult = 255;
squareCount--;
}
break;
case (SINE):
Serial.println("SINE WAVE");
Serial.println("------------------------------------------");
calcResult = 128+128*sin(2*PI*100*(sineOutput/10000.0));
sineOutput++;
break;
case(TANGENT):
Serial.println("TANGENT WAVE");
Serial.println("------------------------------------------");
calcResult = 128+64*tan(2*PI*100*(tangentOutput/10000.0));
tangentOutput++;
break;
default:
Serial.println("DEFAULT");
Serial.println("------------------------------------------");
calcResult = 0;
break;
}
binaryOutput=calcResult;
Serial.print("Binary Output: ");
Serial.println(binaryOutput, DEC);
if (binaryOutput)
{
for (int i = 7; i >= 0; i--)
{
if (binaryOutput >= bitConversion(i))
{
digitalWrite(pin[i], HIGH);
binaryOutput -= bitConversion(i);
Serial.print(1);
Serial.print(" ");
}
else
{
digitalWrite(pin[i], LOW);
Serial.print(0);
Serial.print(" ");
}
}
}
else
{
for (int i = 7; i >= 0; i--)
{
pinMode(pin[i], LOW);
Serial.print(0);
Serial.print(" ");
}
}
Serial.println("\n\n");
delay(50);
}
int bitConversion(int n)
{
int result = 1;
for (int i = 0; i<n; i++)
result *= 2;
return result;
}
关于您项目的一些事情
对于波形发生器,在主循环中生成信号不是一个好主意。正确的方法是使用定时器和计数器(必要时可以中断)。这是因为在数字信号发生器中,采样频率和波形频率很重要,而在主回路中生成波形可能会产生延迟,从而改变频率。使用计数器,您还可以控制输出信号的频率。
顺便说一下,您可以按照自己的方式进行操作,但正如我所说,它有其局限性。
因为您使用 8 位作为输出并且用
calcResult
变量表示,也许您可以考虑将其设为byte
或unsigned char
(两者基本相同)在正弦波的
calcResult
计算中,它说calcResult = 128+128*sin(2*PI*100*(sineOutput/10000.0))
但它应该是calcResult = 128+127*sin(2*PI*100*(sineOutput/10000.0))
因为其他方式你将有calcResult=256
有时。变量
也会发生这种情况triangleCheck
一直在增加,这会导致你溢出。尽管这也可以为您提供正确的行为,但使用取值 0 和 1 的布尔值或字符是更好的方法。squareCheck
.您似乎在主循环的所有迭代中打印有关 incomingByte 的文本,我认为这可能很烦人(并且还占用处理能力)。
看一下切线波,我在正弦波中提到的溢出也有同样的问题。您应该使用信号的周期性来执行此操作。您还应该考虑到切线是一个无界函数,因此它的值将超过您的 DAC 接受的 255。
对于你在最后一部分做的位转换,也许你可以用位掩码来完成。这样会更干净,更容易处理。
如果您不确定自己的 DAC,可以使用拨码开关进行测试。或者,如果可能的话,使用信号发生器,然后是 ADC,然后是 DAC,最后是示波器。这样您将 100% 确定您的 DAC 正在工作。
你测试过Arduino的输出了吗?您可以将带有电阻的 LED 连接到输出引脚,使用方波信号您应该会看到一些非常清晰的行为。
对于正弦波和正切波我建议看一下变量的转换(float to int)。也许关于它是如何完成的没有问题,但是确定您正在处理的信息是很好的。
希望这至少能对您的项目有所帮助。
您好!