I'm porting a project from a teensy microcontroller to the arduino. Essentially the project uses a microcontroller to simulate touchscreen input for the Nintendo 3DS console. I am doing this by unplugging the touchscreen digitizer of my Nintendo 3DS and putting my arduino in its place. See the link below for the original teensy code and schematics that I'm trying to modify. (The oscilloscope picture below is also credit of author of the teensy code) https://github.com/dekuNukem/3xtDS

This is a fairly generic touchscreen I'm trying to simulate input for, so I'm not sure what's going wrong. I am not sure if my schematic has a problem, or if the Arduino's PWM frequency limitation is the problem. The teensy code was setup to output at 90khz, while the highest I can possibly set my arduino is around 31khz. I believe this should be good enough because I believe the Nintendo 3DS only samples at around 100 microsecond intervals.

What I have done:

  • I'm connecting two of my arduino pins to the X+ and Y+ pins where the Nintendo touchscreen digitizer used to be.
  • I have used a voltage divider to change the arduino's output voltage from 5v to 1.8v, which is the VCC of the nintendo device.
  • I have used a 0.22uf capacitor and 1k resistor as a DAC to change the PWM output to analog.

I tried troubleshooting by:

  • using 68 & 120 ohm resistors in my voltage divider for smoother analog PWM response, instead of 68k & 120k resistors
  • adding a 1N914 diode between the capacitor and ground (since I am using ceramic capacitors, which are bidirectional)
  • eliminating the while(analogRead(senseY) < 46) line in my code and instead using a static delay of 100 microseconds

Touchscreen press I want to simulate (Yellow is Y+, blue is X+):

My Schematic: enter image description here

Teensy code ported to arduino:

// I've included the setPwmFrequency() function listed on the arduino site, 
// but I'm omitting it here for clarity reasons.

// The main change between the Teensy and arduino is that the teensy uses 
// software to lower the PWM voltage from teensy's native 3.3v down to the 
// nintendo's 1.8v, while I have instead used a voltage divider on the PWM 
// output of the arduino.

// X+ pin of touchscreen.
int touchX = 9;

// Y+ pin of touchscreen.
int touchY = 10;

// Pin to monitor arduino's output of Y+
int senseY = 11;

void setup() {
  // -Change pins 9 and 10 to have 31,250 hz PWM frequency. This is the 
  // highest I can set it. Teensy originally set their frequency to 90khz.
  // My difference in frequencies MIGHT be the cause of my problems.
  // I picked pins 9 and 10 because they won't affect timing for millis() 
  // and delay. 
  setPwmFrequency(9, 1);
  setPwmFrequency(10, 1);

  // Original teensy code set analog write resolution to 9bits.
  // This was necessary because the nintendo touchscreen is 320x240, which is greater than 255 for an 8bit resolution.
  // However, I don't mind this minor accuracy loss! arduino's analog resolution is accurate enough for me.
  pinMode(touchX, OUTPUT);
  pinMode(touchY, OUTPUT);
  analogWrite(touchX, 0);

void touch_screen_click(unsigned int x, unsigned int y, unsigned int duration_ms) {
  // Calculate PWM value to write  based on the xy touchscreen coordinates we want.
  unsigned int x_potential = ((double)x / 320) * 255;
  unsigned int y_potential = ((double)y / 240) * 255;

  // Start outputting the x value.
  analogWrite(touchX, x_potential);

  // Pull Y+ to ground.

  unsigned int start = millis();

  // Keep touch screen pressed for tap duration.
  while(millis() - start < duration_ms) {
    // wait until Y+ pin is in output mode
    // original teensy code checked for 512, which was half of the max value 1024.
    // we're outputting 1.8v with our circuit, but reading analog at 5v
    // so the value we check for is half of this max value: 1.8/5*255=92
    // I COULD have used arduino's Aref, but math is faster than soldering
    while(analogRead(senseY) < 46)

    // now Y+ pin is in output mode
    analogWrite(touchY, y_potential);

    // pull Y+ down again to keep interrupt going
  analogWrite(touchX, 0);

void disable_touch_screen() {
  analogWrite(touchY, 255);

// pull Y+ pin low to initialize 3DS's touch interrupt
void enable_touch_screen() {
  analogWrite(touchY, 0);

// the loop routine runs over and over again forever:
void loop() {

// tap at 150x150 for 100ms.
touch_screen_click(150, 150, 100);


// tap at 50x50 for 100ms.
touch_screen_click(50, 50, 100);
  • I'm trying to do the same thing with a Nintendo DSi, I'll be watching here :) Apr 20, 2015 at 22:59
  • Why do you wish to monitor the Arduino's Output of Y+? Apr 21, 2015 at 9:53
  • @Austin Burk Which Arduino Board are you using? Apr 21, 2015 at 10:02
  • I'm using an Arduino Uno. Apr 21, 2015 at 16:12
  • 1
    I am monitoring the Y+ pin because the 3DS console sends the touchscreen interrupt on that pin, according to dekunukem's documentation: github.com/dekuNukem/3xtDS/blob/master/overview.pdf From what I understand, he uses a bit of a hack to get this working by using only two of the four pins for the touchscreen. I believe the 3DS uses a standard 4-wire resistive touchscreen such as this: sparkfun.com/datasheets/LCD/HOW%20DOES%20IT%20WORK.pdf
    – Kyohack
    Apr 22, 2015 at 7:35

1 Answer 1


To confirm your analysis that the issue is caused by the lower pwm frequency on the Arduino, did you try reproducing the problem with the teensy? Just divide by 3 the PWM frequency on the Teensy and see if you get the same problems that you are experiencing with the Arduino.

  • 1
    Yes, I have recently purchased a teensy 3.1 specifically for troubleshooting this project and I unfortunately have the same result. This confuses me greatly, because I used the exact same electrical schematic and code listed in dekunukem's documentation that I was referring to. At this point, the only thing I haven't tried is using all 4 pins of the touchscreen rather than just the 2 pin exploit that dekunukem used: sparkfun.com/datasheets/LCD/HOW%20DOES%20IT%20WORK.pdf
    – Kyohack
    Apr 24, 2015 at 8:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.