Is it possible to read PWM as Analog using a digital port?

I am wondering, and hoping that it is possible, to read a PWM using a digital read on a digital I/O port and make it usable information in the form of an analog signal. I wanted to transmit two separate signals from the arduino Esplora to the arduino Robot, and the Esplora is writing the values fine and the Robot is reading the data, except I want to convert the modulating voltages into Analog data some how. I am willing to do this communication in different ways, if anyone has any other ideas that would work.

Why not just have the Esplora send the PWM info as a digital message?
"Hey Robot, I am using analogWrite(xxPin, 57) now"

Which side needs the analog data?

Michael1617:
I am wondering, and hoping that it is possible, to read a PWM using a digital read on a digital I/O port and make it usable information in the form of an analog signal.

PWM is not analog. It is a digital level of 1 (HIGH), followed by a digital level of 0 (LOW). Pulse Width Modulation is the varying of the time the level is 1, and the time the level is 0, within a given 'frame'. You can convert PWM to analog by feeding the PWM signal to an RC (Resistor/Capacitor) filter, which will charge up the capacitor while the signal is HIGH, and discharge it while the level is LOW. The amount of charge/discharge is set by the resistor and capacitor values, and is like a sawtooth waveform, the smoothness of which is dependent on the component values.

I wanted to transmit two separate signals from the arduino Esplora to the arduino Robot, and the Esplora is writing the values fine and the Robot is reading the data, except I want to convert the modulating voltages into Analog data some how. I am willing to do this communication in different ways, if anyone has any other ideas that would work.

As CrossRoads says, you are better off telling the other device what the PWM values are.

CrossRoads:
Why not just have the Esplora send the PWM info as a digital message?
"Hey Robot, I am using analogWrite(xxPin, 57) now"

Which side needs the analog data?

What do you mean by message? And the Esplora is writing a value to a digital pin which sends the value to the Robot which needs to somehow write a motor value between 0 and 255. That is done with two digital pins on the Esplora and two digital pins on the Robot to control each motor on the Robot.

lar3ry:
Pulse Width Modulation is the varying of the time the level is 1, and the time the level is 0, within a given 'frame'. You can convert PWM to analog by feeding the PWM signal to an RC (Resistor/Capacitor) filter, which will charge up the capacitor while the signal is HIGH, and discharge it while the level is LOW.

I understand PWM, but how would I determine the resistor and capacitor to Use?
And by the way, the Robot reads the LOW as 0 and the HIGH as 1023 since it is using analogread(). I get patterns of 0 and 1023 when displaying the output with serial on my computer.

Michael1617:
how would I determine the resistor and capacitor to Use?

You could use a RC filter design tool. The actual value will depend on the impedance of whatever you're connected to. If it is the analog-in of another arduino, it is a relatively high impedance.
https://www.google.com/search?q=PWM+RC+filter

Michael1617:
I understand PWM

You sure? Your next statement seems to indicate maybe you don't fully understand it.

Michael1617:
I get patterns of 0 and 1023 when displaying the output with serial on my computer.

That's how PWM works. It's pulse-width-modulation. The signal goes from low (0v or 0 on the a/d) to high (5v or 1023 on the a/d). The amount of time the signal stays high or low is what PWM changes, not the voltage.

I was just clarifying.

And thanks for that suggestion! But how would I determine the frequency of the PWM?

Michael1617:
But how would I determine the frequency of the PWM?

Other than measuring it?

Third sentence.

Michael1617:
What do you mean by message? And the Esplora is writing a value to a digital pin which sends the value to the Robot which needs to somehow write a motor value between 0 and 255. That is done with two digital pins on the Esplora and two digital pins on the Robot to control each motor on the Robot.

What he means is that it you are sending a PWM signal, and the only way to receive a PWM signal on the other end (if the other end is another arduino), is to measure the duration of it, and to know the durarion of the entire cycle. The message is the duty cycle, so it would be better to just tell the other end what the duty cycle is.

In simpler terms, assuming you have done an analog write of 100, setting the duty cycle to 100 out of a total frame of 255, you can gather that information at the other end, only by measuring the incoming pulses, but you could gather that information at the other end by telling it that the duty cycle is 100.

I understand PWM, but how would I determine the resistor and capacitor to Use?
And by the way, the Robot reads the LOW as 0 and the HIGH as 1023 since it is using analogread(). I get patterns of 0 and 1023 when displaying the output with serial on my computer.

Doesn't matter. A digitalRead would return a value of 0 or 1, LOW or HIGH. AnalogRead will return a result of 0 or 1023, also a LOW or HIGH, but in analog-scaled values. The POINT is that just reading a level on an input pin connected to a PWM output will NOT give you any indication of the duty cycle of the PWM signal.

lar3ry:
What he means is that it you are sending a PWM signal, and the only way to receive a PWM signal on the other end (if the other end is another arduino), is to measure the duration of it, and to know the durarion of the entire cycle. The message is the duty cycle, so it would be better to just tell the other end what the duty cycle is.

In simpler terms, assuming you have done an analog write of 100, setting the duty cycle to 100 out of a total frame of 255, you can gather that information at the other end, only by measuring the incoming pulses, but you could gather that information at the other end by telling it that the duty cycle is 100.

Are you saying there is another way to tell it (the robot) that the cycle is 100 than having it figure it out using the PWM signal?

I am not finding a way to do this, I have read that I can pick almost any capacitor and just have a corresponding resistor that works in a certain equation I think, but otherwise I don't know where to start. I know I have a range of 0v to 5v range. I would also like to use either 100uF, 100nF, or 100pF capacitors (I got them in the official arduino starter kit a while ago), but if you can tell me something else that will work, I guess I could buy one.

Michael1617:
Are you saying there is another way to tell it (the robot) that the cycle is 100 than having it figure it out using the PWM signal?

Yes.

Use SPI, I2C, or SoftwareSerial to transfer a number that the robot can then use to set a PWM pin to control a speed, or to do whatever else you want to do with the PWM signal that you would have sent from the Esplora.

You can use one of these interfaces to control both motors. Just send something like “#100,200*” then at the other end, you set the PWM to the motors as 100 and 200. The # tells you it’s the start of a message and the * tells you it’s the end of the message. The commas i useful for separating the numbers, so you can send something like #9,220*, without having to decide where 9220 should be split for motor 1 and motor 2.

Of course, you can choose whatever delimiters you want.

lar3ry:
Use SPI, I2C, or SoftwareSerial to transfer a number that the robot can then use to set a PWM pin to control a speed, or to do whatever else you want to do with the PWM signal that you would have sent from the Esplora.

You can use one of these interfaces to control both motors. Just send something like “#100,200*” then at the other end, you set the PWM to the motors as 100 and 200. The # tells you it’s the start of a message and the * tells you it’s the end of the message. The commas i useful for separating the numbers, so you can send something like #9,220*, without having to decide where 9220 should be split for motor 1 and motor 2.

Of course, you can choose whatever delimiters you want.

I know that the Esplora is not configured for I2C and I don’t think I can use SoftwareSerial to send messages between 2 arduinos, and they would have to be connected to a computer right? As I was typing that the thought occored to me that I could connect the serial ports to each other, right? In to out and out to in for each device? Would that work? Because that would simplify everything. I have attempted SPI communication Between the two, and I had lots of trouble so I tried to do what I posted as a question in this thread.

Michael1617:
I can use SoftwareSerial to send messages between 2 arduinos, and they would have to be connected to a computer right?

No

Michael1617:
As I was typing that the thought occored to me that I could connect the serial ports to each other, right?

Yes, which is what you could do with SoftwareSerial. "Software" means not-dedicated-hardware on the microcontroller (like an UART), not something PC related.

I would simply connect the Rx to tx from arduino to arduino, however, I am having trouble determining where the Rx and tx ports are on the robot.

Michael1617:
I would simply connect the Rx to tx from arduino to arduino, however, I am having trouble determining where the Rx and tx ports are on the robot.

If you’re using the Arduino Robot, you won’t find RX/TX pins. They’re in use by the boards of the Robot itself already.

If you're using the Arduino Robot, you won't find RX/TX pins. They're in use by the boards of the Robot itself already.
[/quote]

So what should I do then?

SoftwareSerial

Oh! I see, thanks so much!!!

I got this error ONLY when compiling for the robot (it was OK if I compiled the robot code for, say, the Uno) , the Esplora was fine.

C:\Program Files\Arduino\arduino-1.0.5\libraries\SoftwareSerial\SoftwareSerial.cpp: In member function 'void SoftwareSerial::begin(long int)':
C:\Program Files\Arduino\arduino-1.0.5\libraries\SoftwareSerial\SoftwareSerial.cpp:399: error: 'digitalPinToPCICR' was not declared in this scope
C:\Program Files\Arduino\arduino-1.0.5\libraries\SoftwareSerial\SoftwareSerial.cpp:401: error: 'digitalPinToPCICRbit' was not declared in this scope
C:\Program Files\Arduino\arduino-1.0.5\libraries\SoftwareSerial\SoftwareSerial.cpp:402: error: 'digitalPinToPCMSK' was not declared in this scope
C:\Program Files\Arduino\arduino-1.0.5\libraries\SoftwareSerial\SoftwareSerial.cpp:402: error: 'digitalPinToPCMSKbit' was not declared in this scope
C:\Program Files\Arduino\arduino-1.0.5\libraries\SoftwareSerial\SoftwareSerial.cpp: In member function 'void SoftwareSerial::end()':
C:\Program Files\Arduino\arduino-1.0.5\libraries\SoftwareSerial\SoftwareSerial.cpp:417: error: 'digitalPinToPCMSK' was not declared in this scope
C:\Program Files\Arduino\arduino-1.0.5\libraries\SoftwareSerial\SoftwareSerial.cpp:418: error: 'digitalPinToPCMSKbit' was not declared in this scope

If you want to send a number between two Arduinos, sending it via a digital signal (e.g. an async serial data stream) seems like the simplest and most reliable way.

If you're dead set on sending it via a PWM signal and measuring the duty cycle at the receiving side to work out the approximate duty cycle, you could do it with moderate complexity and very low latency by measuring the high and low pulse lengths or with simpler code and more latency by just reading the input state at regular intervals and averaging the result over a lot of samples.

PeterH:
If you’re dead set on sending it via a PWM signal and measuring the duty cycle at the receiving side to work out the approximate duty cycle, you could do it with moderate complexity and very low latency by measuring the high and low pulse lengths or with simpler code and more latency by just reading the input state at regular intervals and averaging the result over a lot of samples.

I’m not. I really don’t want to do it that way. I just want something that will work to send 2 integers (between 0 and 255). I2C is out of the question because the Esplora is not compatible. I don’t want to use SPI. I want to use SoftwareSerial, but I got that error that is above your post. If you can help, please do.