Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Nvidia Jetson Series Support #23

Merged
merged 14 commits into from
Mar 24, 2022
Merged

Conversation

pjueon
Copy link
Contributor

@pjueon pjueon commented Feb 13, 2022

related to #22

  • Tested on Jetson Nano & JJY based watch (Citizen REGUNO KL8-911-71), with both JJY40 and JJY60.
  • Can choose the platform by the cmake option PLATFORM. (ex> -DPLATFORM=jetson)
    • default value is rpi
  • Isolate the platform-specific information from the main logic so that the new other platform supports could be easily added in the future.

Main differences from Raspberry Pi platform:

- create emums.h
- add SetTxPower method to GPIO class
- can choose platform by cmake option "PLATFORM"
(default value is rpi)
- rename files and do refactoring
- change directory structures
- add description for jetson
- add images for jetson
@hzeller
Copy link
Owner

hzeller commented Feb 13, 2022

Very nice, thanks! I'll have a first look at the PR.

I think we can't leave out the attenuation feature as some time signals require it; for instance DCF77 has the carrier always on, but specifically calls for attenuation. So for completeness and feature parity with the Raspberry Pi hardware, we need both LOW and OFF.

Copy link
Owner

@hzeller hzeller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice!
The separation of the hardware interfaces is nicely done, I like the separation into directories.

I just have a few smallish remarks before we're ready to merge.

.gitignore Outdated

# End of https://www.toptal.com/developers/gitignore/api/linux,visualstudiocode

build/*
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does look like a lot of IDE gnerated stuff in here that should not necessarily make it upstream; every developer with specific IDEs should keep their .gitignore with whatever is needed in theri context.

So here, we can just simplify the additions to .gitignore tobuild/* to accomodate the cmake-project.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#ifndef ENUMS
Copy link
Owner

@hzeller hzeller Feb 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd call this include-guard after the file, so CARRIER_POWER_H

@@ -15,20 +15,21 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#ifndef RPI_GPIO_H
#define RPI_GPIO_H
#ifndef RPI_CONTROL_H
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simiilar here: let's derive the include-guard from the filename RPI_HARDWARE_CONTROL_IMPLEMENTATION_H

#endif // RPI_GPIO_H
using GPIO = HardwareControl::Implementation;

#endif
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure to have a newline at the end of each file (the .editorconfig file also will configure that)

@@ -50,15 +51,18 @@ class GPIO {
// not possible.
double StartClock(double frequency_hertz);
void StopClock();

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't leave trailing whitespaces in lines.
(I have just added a .editorconfig file so that it is easier to automatically do, as most editors can use that file).

README.md Outdated

We use hardware PWM pin as a frequency output pin. Unlike the Raspberry Pi, we need only one output pin
because we modulate the signal by switching (on-off keying) instead of attenuating.
And we use only one register (4.7kΩ) for the Jetson.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/register/resistor/

Here's the full schematic of the external hardware for Jetson Series:
Schematic | Real world
-------------------------------|------------------------------
![](img/schematic-jetson.jpg) |![](img/jetson-nano.jpg)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a biggie, but the 'real world picture' would be even better if the viewer could better see where the pins are connected on the Pin header. So more taking a picture from the right side so that you can see onto the full pin-header and see which pins are connected while still having the watch in the foreground.

README.md Outdated
On Jetson, the external hardware setup is slightly different from Raspberry Pi.

We use hardware PWM pin as a frequency output pin. Unlike the Raspberry Pi, we need only one output pin
because we modulate the signal by switching (on-off keying) instead of attenuating.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, some of the signals require attenuation to be in spec. So if you want to skip implement attenuation in the first step, maybe point out that it might not work in all circumstances.

@pjueon
Copy link
Contributor Author

pjueon commented Feb 14, 2022

Thanks for the detailed feedback!
I'll fix it when I get home.

@pjueon
Copy link
Contributor Author

pjueon commented Feb 14, 2022

Facing some troubles in attenuating the signal.
example

When I set the attenuation pin as output and set it LOW, the voltage at "A" doesn't decrease at all.
And the voltage at the attenuation pin remains ~0.35V not 0V. (output pin is ~1.5V)

I'm assuming that the voltage at attenuation pin is being pulled-up to the output pin, but I'm not familiar with HW stuff, I'm not sure...

If you have any suggestion please let me know.

@hzeller
Copy link
Owner

hzeller commented Feb 14, 2022

If the voltage is 1.8V, this indidcates that the GPIO ports are connected to the internal core voltage of the CPU and they will have issue to drive anything and it will probably dangerous to even connecting the coil, as these tiny mosfets in the output stage will not be able to move the current.

I strongly suggest to connect the GPIO pins via a 1.8V -> 3.3V level shifter to (a) relieve the GPIO pins (b) have enough drive strength for the external components such as coil and pulldown.

@pjueon
Copy link
Contributor Author

pjueon commented Feb 15, 2022

If the voltage is 1.8V, this indidcates that the GPIO ports are connected to the internal core voltage of the CPU and they will have issue to drive anything and it will probably dangerous to even connecting the coil, as these tiny mosfets in the output stage will not be able to move the current.

I strongly suggest to connect the GPIO pins via a 1.8V -> 3.3V level shifter to (a) relieve the GPIO pins (b) have enough drive strength for the external components such as coil and pulldown.

I have too little knowledge about HW stuff to understand what you're suggesting, Sorry. Could you explain with a picture please?

And when I asked this problem to Nvidia developers forum, someone linked this pdf. Maybe it's related.
customizing_the_jetson_nano_40-pin_expansion_header_v1.2.pdf.pdf

It's about the "level shifters" in Jetson Nano, but I cannot understand it. I don't even know what "level shifters", "buffers", "driving" mean...

@icb-
Copy link
Contributor

icb- commented Feb 15, 2022

A level shifter translates a signal with one voltage (like 1.8V) to a signal with a different voltage (like 3.3V). A buffer takes a signal and repeats it on its output. Buffers can often do level shifting, depending on their input thresholds.

In the circuit below, you have two tri-state buffers doing level shifting. Tri-state means the output can be driven (set to a low or high signal) or can be set "tri-stated" or "high-Z" and effectively disconnected (not driven high or low). When the output enable signal (the one at the bottom of the triangle) is low, the output signal is driven. When it's high, the output is disconnected. The circle means it's an active-low or inverted signal.

The "PWM" signal is passed through, and raised to a higher voltage. It is always driven.

The "A̅T̅T̅E̅N̅U̅A̅T̅E̅" (the overline means an active low signal) signal causes the output to be pulled lower (attenuate the voltage across the inductor) when pulled low. I haven't read through all of your code, so you may need to invert the attenuate signal in software to attenuate when you need the signal attenuated.

The inductor is the "antenna".

Something like 74LV1T125 should be suitable for this level shifting. They should be powered by a 3.3V supply. A 74LVC125 may work too, but the would be operating out of spec (it wants 2V on its input for a high signal when powered from 3.3V)

Screen Shot 2022-02-15 at 7 50 29 AM

@pjueon
Copy link
Contributor Author

pjueon commented Feb 15, 2022

@icb- Thank you very much. I think I kind of understand.

So a buffer is something like a transistor, right? Fortunately I had a couple of transistors so I tried this setup:
new_setup_jetson

I changed the code a bit (setting the attenuation pin to high to attenuate the signal), and It WORKS!!

So I need 2 NPN transistors for this. Is there any better/simpler setup? (ex> works with only one transistor)

@icb-
Copy link
Contributor

icb- commented Feb 15, 2022

So a buffer is something like a transistor, right?

Not quite.

A buffer like in the 74125 can drive the output high, low, or high impedance (not driven, tri-state, high-Z). It's a digital device.

A BJT like you have in your circuit works kind of like a switch. It's not quite a switch, it's a current amplifier, but that's a good enough analogy for now. You should use a PNP BJT on the high side instead of the NPN you have in your diagram.

That might be good enough for how this circuit works.

You're not going to get away with less than two transistors. One is switching the higher voltage across the "antenna" from the PWM signal. The other is switching in a resistor in parallel to the "antenna" to attenuate the signal.

It might help to redraw the circuit more like this to show the two parallel current paths, the "antenna" and the attenuator.

Screen Shot 2022-02-15 at 1 35 28 PM

I say "antenna" in quotes and draw it as an inductor, because I don't think this is really acting as a radio transmitter, but is inductively coupling the signal into the antenna on the clock.

@pjueon
Copy link
Contributor Author

pjueon commented Feb 16, 2022

You should use a PNP BJT on the high side instead of the NPN you have in your diagram.

Why? At the moment I only have NPN transistors. And I thought there would be no difference for our application. Is there any difference?

@pjueon
Copy link
Contributor Author

pjueon commented Feb 16, 2022

If the voltage is 1.8V, this indidcates that the GPIO ports are connected to the internal core voltage of the CPU and they will have issue to drive anything and it will probably dangerous to even connecting the coil, as these tiny mosfets in the output stage will not be able to move the current.

I strongly suggest to connect the GPIO pins via a 1.8V -> 3.3V level shifter to (a) relieve the GPIO pins (b) have enough drive strength for the external components such as coil and pulldown.

After reading the following document many times( and thanks to icb-'s explanation) ,I think I'm just starting to understand it.

customizing_the_jetson_nano_40-pin_expansion_header_v1.2.pdf.pdf

According to this document, the Jetson Nano's GPIO pin headers are already connected to the level shifters (TXB0108).

image

When I set the GPIO output to HIGH, the pin is being pulled up to 3.3v by 4k ohm internally.
And when I set it to LOW, it is being pulled down to the GND with 4k ohm internally.

When I said the output pin voltage was ~ 1.5V, I connected 4~5k ohm to the pin.
If I connected ~25k ohm to the pin and set the pin HIGH (without PWM) I got ~3V.

From the document:

The TXB0108 devices are not intended for use in open-drain applications or to drive low impedance (i.e. directly driving an LED) or high capacitive loads (i.e. driving a long wire, or multiple loads).

So maybe I should use more registers. The reason why I couldn't pull down the signal to the GND even if I set the pin to LOW from my first setup, it's probably because the pin is internally pulled down to GND with 4k ohm. I'll give a try again with higher registers !

@icb-
Copy link
Contributor

icb- commented Feb 16, 2022

You should use a PNP BJT on the high side instead of the NPN you have in your diagram.

Why?

That's just how transistors work. To fully turn an NPN BJT on (saturate), the base needs to be at a higher voltage than the collector. If you have it on the high side of the circuit, you can't ever reach that. There are lots of explanations of why on the Internet, like this one and this one and the linked resources from them.

Technically, you should also have a resistor between the control pins and the base of each transistor to limit the base current, but it looks like your level shifter is already doing that for you.

If you need to use only NPN transistors, it would be better to drive it from the low side like this.

Screen Shot 2022-02-16 at 7 35 13 AM

The TXB0108 devices are not intended for use in open-drain applications

This is why you can't drive the attenuate signal directly from the level shifter. You need to be able to drive it low, but not high. That's what open-drain is (or open-collector with BJTs). You may be able to drive the PWM signal directly from the level shifter, and the ATTENUATE signal with a transistor like this, if the level shifter can source enough current.

Screen Shot 2022-02-16 at 7 59 23 AM

@pjueon
Copy link
Contributor Author

pjueon commented Feb 16, 2022

@icb- I just tested the second image you posted, and it DOES work!

Screen Shot 2022-02-16 at 7 59 23 AM

That's just how transistors work. To fully turn an NPN BJT on (saturate), the base needs to be at a higher voltage than the collector. If you have it on the high side of the circuit, you can't ever reach that.

I see! I really didn't know that. Thanks again for your kind explanation.
I truly had zero knowledge about this kind of stuff, haha.

Please forgive me to ask one more basic question.
I found this setup from this video: https://youtu.be/6SHGAEhnsYk?t=596

image

This setup looks like switching the signal instead of attenuating it. Is my understanding correct?

- add an attenuation pin like the rpi
- add a NPN transistor to the attenuation pin.
This transistor is added because
it was not possible to attenuate the signal
directly from the GPIO on the Jetson Nano. See hzeller#23 for more details.
@icb-
Copy link
Contributor

icb- commented Feb 16, 2022

This setup looks like switching the signal instead of attenuating it. Is my understanding correct?

It's doing both. It's operating the transistor in its active region, where it's amplifying the base-emitter current.

When GPIO4 is high, a small current flows into the base, resulting in a large current flowing through the transistor collector-emitter. This is because R3 is a relatively high value, so a relatively smaller current flows into the base.

When GPIO17 is high, a larger current flows into the base resulting in an even larger current flowing through the transistor collector-emitter. This is because R2 is a relatively low value, so a relatively larger current flows into the base.

When both GPIO4 and GPIO17 are high, you have a still larger current.

@pjueon
Copy link
Contributor Author

pjueon commented Feb 16, 2022

This setup looks like switching the signal instead of attenuating it. Is my understanding correct?

It's doing both. It's operating the transistor in its active region, where it's amplifying the base-emitter current.

When GPIO4 is high, a small current flows into the base, resulting in a large current flowing through the transistor collector-emitter. This is because R3 is a relatively high value, so a relatively smaller current flows into the base.

When GPIO17 is high, a larger current flows into the base resulting in an even larger current flowing through the transistor collector-emitter. This is because R2 is a relatively low value, so a relatively larger current flows into the base.

When both GPIO4 and GPIO17 are high, you have a still larger current.

I see. Thank you very much!

@pjueon
Copy link
Contributor Author

pjueon commented Feb 16, 2022

@hzeller
I've just pushed some commits to this branch.
Could you check if I properly fixed everything I need to?

- remove the IDE-specific configuration
@pjueon
Copy link
Contributor Author

pjueon commented Feb 16, 2022

Oops, I almost forgot to update the .gitignore file. Fixed it now!

- added a new line at the end of the file
@JDat
Copy link

JDat commented Feb 16, 2022

Pardon my electronics!
1st schematic (two transistors in series) doesn't looks good, because if lower transistor is closed, upper will get negative bias on base relative to emitter.

Las schematic (different GPIOs on one transistor base) looks fine, but need some fine tuning with base resistors. Not for beginners.

What about this schematic? More components, but... Fine tune R6 (set and forget + share to community) and that's it!
PS: Even if I like R2 and R4, they can be omitted.

2022-02-16-194657_1366x744_scrot
.

@pjueon
Copy link
Contributor Author

pjueon commented Feb 17, 2022

Pardon my electronics! 1st schematic (two transistors in series) doesn't looks good, because if lower transistor is closed, upper will get negative bias on base relative to emitter.

Las schematic (different GPIOs on one transistor base) looks fine, but need some fine tuning with base resistors. Not for beginners.

What about this schematic? More components, but... Fine tune R6 (set and forget + share to community) and that's it! PS: Even if I like R2 and R4, they can be omitted.

2022-02-16-194657_1366x744_scrot .

Thanks for the advice!
Hmm, then how do you think about this one? Personally I like it because it only requires 1 transistor and looks relatively simple for me.

Screen Shot 2022-02-16 at 7 59 23 AM

I tested this setup and it works well. So if you think this setup has no big issue, I think it would be good enough for this project.

@pjueon
Copy link
Contributor Author

pjueon commented Feb 24, 2022

Reminder.
@hzeller Could you check this please?

What I fixed:

  • added a new line at the end of the files
  • changed the setup
    • the level shifter was not needed because it was already included in the Jetson devices
    • now it modulates the signal by attenuating the pwm signal instead of turning on/off
  • changed README
  • changed the images
  • fixed macro names

@pjueon
Copy link
Contributor Author

pjueon commented Mar 13, 2022

Reminder again.
@hzeller

Could you check this please...?

@pjueon pjueon requested a review from hzeller March 13, 2022 15:13
Copy link
Owner

@hzeller hzeller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!
Sorry for the delay, sometimes notifications from github vanish in the noise of email :)

@hzeller hzeller merged commit 483c679 into hzeller:master Mar 24, 2022
@pjueon pjueon deleted the jetson_support branch May 18, 2022 09:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants