Arduino Forum

Topics => Device Hacking => Topic started by: frankwilsonshat on Jun 26, 2016, 05:00 pm

Title: Projector ballast bypass
Post by: frankwilsonshat on Jun 26, 2016, 05:00 pm
I'm trying to get my projector to stay on without the lamp so I can change the bulb for an LED.
It's an NEC NP300, I've read the data from pin 1 on the ballast connector on Saleae Logic.
Unfortunately it appears to be a 24Mhz signal, this may be too high for playback on the Ardunio?
I know the projector will stay on if this 3.3V signal is present.
I have an Arduino Uno and an Arduino pro mini
So my question is
does anyone have a sketch I could try?
Frank
Title: Re: Projector ballast bypass
Post by: Riva on Jun 27, 2016, 08:35 am
Your not going to get a 24MHz signal out of the Arduino(s) you have as they only clock in at 16MHz.
Maybe something like the Teensy3.1 (http://www.pjrc.com/teensy/index.html) would do this but best check to be sure first. Does the signal need to be 24MHz?
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jun 27, 2016, 10:38 am
Does the signal need to be 24MHz?
I wondered that too, thinking that if I ran a capture program on the Arduino at 16Mhz and sent it back to the projector, and see if it would work.

However there are the occasional 41.67 nano second pulses, as if NEC deliberately went out of their way to stop anyone bypassing the ballast, (back in 2009 anyway, when it was released)

(http://i64.tinypic.com/2d1957b.png)

And more

(http://i68.tinypic.com/7269vd.png)

Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jul 11, 2016, 10:36 pm
Okay my bad, turns out I'm looking at a 2600baud serial stream (UART?) the 24Mhz sampling was overkill, plus I was getting glitches,

Here's my progress so far;

(https://s32.postimg.org/o36ywavhx/optorun3.jpg) (https://postimg.org/image/p5h5eueb5/)photo hosting sites (https://postimage.org/)

All I want to do is send this serial stream back to the projector from the Arduino (I'm using an optocoupler off a spare NP300 to keep the beamer happy with the 3.3 Volt logic level)

It's a series of 10bit bytes, 1 stop bit, no parity.
There's a few bytes at first then a regular series of 3 bytes with a varying delay of about 1 second between them.

Here's my idea for the sketch;
-------------------------------------------------------------------------

 void setup(){
  Serial.begin(2600);
}

  void loop(){

  Serial.write(0x22D); // send this 10 bit byte
  Serial.write(0x139); // send this 10 bit byte
  Serial.write(0x2C1); // send this 10 bit byte

  delay (1041);

  Serial.write(0x20C); // send this 10 bit byte
  Serial.write(0x2C1); // send this 10 bit byte

  delayMicroseconds (9513); 

  Serial.write(0x02C); // send this 10 bit byte
  Serial.write(0x20C); // send this 10 bit byte

  delay (4671); 

   //Loop: While 1
   while (1)
   {

  Serial.write(0x2C1); // first of three byte sequence
  Serial.write(0x02C); // second byte of repeating sequence
  Serial.write(0x20C); // third byte of repeating sequence

  delay (1000);

  // not bothered about the shutdown sequence, once it's on I plan on keeping it running.
  }
  }

---------------------------------------------------------------------

Can someone convert my idea into valid Arduino code?
I'm confused on how to send a 10bit byte of 8 bit serial as I believe it has to be sent as two bytes
MSB LSB etc.
Also would I just be better off just reading the 2600 baud signal on the Arduino to a file and then writing a sketch to send it back?
Frank
Title: Re: Projector ballast bypass
Post by: Riva on Jul 14, 2016, 08:11 am
Quote
It's a series of 10bit bytes, 1 stop bit, no parity.
So to be sure of this you think it's 1 start bit, 10 data bits, 1 stop bit.
Or could it be 1 start bit, 9 data bits, 2 stop bits (or 1 stop bit & 1 parity bit).

If it's not standard serial protocol then just write a little bit banging function that you pass the 10 bit number to and it toggles an output pin with the correct timing to emulate your signal.
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jul 14, 2016, 09:48 am
That's the thing, I'm not sure, it's open to interpretation, a program to send the bits out would be just what I'm after.
How would I go about it though, I've tried it with digital.write and I'm not getting accurate/consistent timings, would need to be done with serial.write AFAIK?

(https://s31.postimg.org/f64pz1d2f/Screenshot_1.jpg) (https://postimg.org/image/f64pz1d2f/)


However serial.write seems to be fixed at 8bit(data), confusing for me, and since this is a one off project I'm not wanting to get out of my depth just a little bit banging function as you mentioned sounds like the plan.
Title: Re: Projector ballast bypass
Post by: Riva on Jul 14, 2016, 10:34 am
The signal looks like it could be 1 start bit , 9 data bits, 2 stop bits but as you need to send so few values repeatedly then maybe just put them into a timings table and send then that way.

As an example here is some code I wrote to send a captured wireless doorbell code so I could trigger the doorbell receiver without pressing the doorbell button.
You could turn the loop code into a function that you pass the timing array as a parameter and then call it with the three one off startup codes from setup() and then write a loop procedure to call it with the repeat the same coded every second, forever.

Code: [Select]
// High/Low microsecond timings, first value is low timing, the rest alternate high/low
const uint16_t hlUsTimings[] = {
  32,999,999,32,32,999,999,32,32,999,999,32,32,999,32,999,
  32,999,32,999,32,999,32,999,32,999,999,32,32,999,32,999,
  32,999,999,32,32,999,999,32,32,999,999,32,32,999,32,999,
  32,32};
const uint8_t hlUsSize = sizeof(hlUsTimings) / sizeof(hlUsTimings[0]);

const uint8_t outPin = 3;                         // Transmitter output pin
const uint8_t ledPin = 13;                        // LED output pin

void setup() {
  pinMode(ledPin,OUTPUT);
  pinMode(outPin,OUTPUT);
  digitalWrite(outPin,LOW);
}

void loop() {
  digitalWrite(ledPin,!digitalRead(ledPin));
  noInterrupts();
  delay(10);
  for (uint8_t y = 0; y < hlUsSize; y++){
    digitalWrite(outPin,!digitalRead(pinState));  // Flip the pin
    uint32_t z = hlUsTimings[y];
    delayMicroseconds(z);
  }
  interrupts();
}


Can you zip up the Salea logic capture and attach it here or somewhere else people can get to it. That way I can hopefully load it in and check the results.
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jul 14, 2016, 12:29 pm
Thanks for the code you posted, I have attached the zip.
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jul 14, 2016, 04:59 pm
I'm running into problems, I have the timings of all the bytes used;

 0x22Dstart[] = {2222,384,444,1212,444,384,444,384,858}; // 0x22D with start delay/low

 0x22D[] = {384,444,1212,444,384,444,384,858};        // 0x22D normal

 0x139[] = {798,444,798,858,798,858};                     //0x22D

 0x2C1[] = {384,444,382,860,1624,860};                   //0x2C1

 0x20C[] = {384,444,2040,444,798,444};                   //0x20C

 0x02C[] = {2040,444,384,444,795,445};                   //0x02C 




I would need to write an array for each one and then call these arrays in the code, add any delays, and loop the three byte repeating sequence.
Title: Re: Projector ballast bypass
Post by: Riva on Jul 14, 2016, 07:02 pm
Thanks for the code you posted, I have attached the zip.
Just tried to have a quick look at the zip data but for some reason it won't load into my LLC software. Maybe your using a newer version than me. I will try and look again tomorrow at home.
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jul 14, 2016, 08:38 pm
I was on version 1.2.08, now on 1.2.10 and my logic save loads ok on that.
Can re upload new zip if necessary
Title: Re: Projector ballast bypass
Post by: Riva on Jul 15, 2016, 09:38 am
I was on version 1.2.08, now on 1.2.10 and my logic save loads ok on that.
I have version 1.1.15 installed so that's probably the cause.

You don't seem to have enough high/low transitions in the timing arrays you created but as I cannot read the Salea file I cannot be sure.
Attached is a possible means to do the job but you would need to check its output and compare to what you want.
This would easily run on a smaller AVR like the Tiny85 if you needed to reduce size.
Title: Re: Projector ballast bypass
Post by: Riva on Jul 15, 2016, 11:42 am
Okay, I downloaded the latest Saleae software onto my other PC (I don't want to risk mixing versions between work and home) and the file loads okay now.
Checking it and I have to disagree with your 2600,10,N,1 serial protocol assumption as it looks more like 2400,9,N,1 to me.
This opens another option to you as you could find a serial library that supports 9 bit data and just use that to send the byte data or just continue down the bit banging route.
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jul 15, 2016, 03:48 pm
Quote
Checking it and I have to disagree with your 2600,10,N,1 serial protocol assumption as it looks more like 2400,9,N,1 to me.
You are absolutely right, after adjusting the analyser settings in Saleae to 2400,9,N,1
all looks 100%.

I'll have a go with your code first of all, and like you point now there's the option for using a 9bit library.
As this is a one off project I'm more than happy to stick with bit banging code you posted.

Thanks for your help, 
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jul 15, 2016, 09:06 pm
I noticed my delays were off, I have sorted these, now when I run the code I am getting the first bit of each byte (or start byte of each byte sequence) as a state change, but after this first high I am not getting the remaining changes.
It's as if the first number in the array is being read, but not the following numbers.
So it's almost there if I could find out why the array is not being read?
Title: Re: Projector ballast bypass
Post by: Riva on Jul 16, 2016, 09:11 am
Try the below code.
You will need to adjust the timing arrays to match you findings but it now does all the values in an array and not just the first one over.
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jul 17, 2016, 02:24 pm
Have updated your code with my new timings.
Had to experiment a little with the numbers to get as close a match to the original signal as possible as this seems quite critical to the projector.
Your code works 100%, no issues at all with that:-)
The projector now starts up as it would when the bulb and ballast are good, albeit with the ballast disconnected and the bulb removed.
Where I'm running into problems is with the repeating sequence, there seems to be more to this than just a regular pulse, the timings possibly.


I have added more lines of code to try and emulate the timings of the original;

delay(3528);

  xSend 3 bytes
 
delay(3108); 

 xSend 3 bytes

delay(3239)
etc,etc            (May have to run original again for longer to check for repetition, can't see any so far)


before I did this it was getting to this point and cutting off, now it does run for longer, however it is still cutting off so I am looking at running the SA again on the complete projector for a closer look.
I have a number of options here, suffice to say I'm fairly confident the projector is very close to staying on.
I may even do what I did before and run it next to the good projector with the ballast wire and gnd wires linked over to check what happens on a longer run time etc.

 
Title: Re: Projector ballast bypass
Post by: Riva on Jul 18, 2016, 08:16 am
As the signal your trying to emulate is a serial signal it might have both the RX & TX connected, and maybe the module/thing that is sending it only does so when requested by the ballast?
might be worth looking for a return serial signal (or maybe something as simple as a line pulsed high/low) from the ballast that is a request signal.
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Jul 19, 2016, 07:37 pm
Quote
As the signal your trying to emulate is a serial signal it might have both the RX & TX connected
That's what it's doing, I'm going to have to reorganise my setup and take another look, not had a chance to do much at the moment.

There's a 2400 baud signal being sent out by the projector to the ballast, will write back as soon as I've got an idea on the bytes being sent.
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Aug 07, 2016, 09:16 pm
Sorry for the delay on this, after moving to a more practical area to continue with this project I am getting plagued with noise on the signal analyser, however after applying a glitch filter to the data I can confirm it is indeed just a single pulse that is being sent from the projector to the ballast.
I'm thinking that some sort of amendment to the code like this might be worth a try,


  if DigitalRead = HIGH then

  xSend(x22D, s22D);
  xSend(x139, s139);
  xSend(x2C1, s2C1);
 
  if DigitalRead = HIGH then

 
  xSend(x20C, s20C);
  xSend(x2C1, s2C1);
 
  if DigitalRead = HIGH then
 
  xSend(x02C, s02C);
  xSend(x20C, s20C);


 
Title: Re: Projector ballast bypass
Post by: Riva on Aug 08, 2016, 10:19 am
Does the serial data transmission start on the rising edge of the pulse or the falling edge? The pseudo code you posted is the right idea but you might need to wait for the pin to go low after sending a serial burst else the code might move on to the next section while the pulse pin is still high.
Code: [Select]
if DigitalRead = HIGH then

  xSend(x22D, s22D);
  xSend(x139, s139);
  xSend(x2C1, s2C1);

 while (DigitalRead == HIGH){};

Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Aug 08, 2016, 07:58 pm
From what I can see the logic level starts high (normal) then drops low, back to high, then the ballast sends back the 9bit serial data 22D,139,2C1 etc.
So every time pin 1 goes low and back to high the data is sent, if that makes sense?
Title: Re: Projector ballast bypass
Post by: Riva on Aug 09, 2016, 11:18 am
From what I can see the logic level starts high (normal) then drops low, back to high, then the ballast sends back the 9bit serial data 22D,139,2C1 etc.
So just reverse the logic and have something like this before each sequence send
Code: [Select]

while (DigitalRead == HIGH){};// Wait till pin goes low
while (DigitalRead == LOW){};// Wait till pin goes high
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Aug 09, 2016, 09:40 pm
I've changed over to another projector due to various problems, now I'm getting a clean signal into the Saleae.
I can now see a 9bit serial signal (2400/9-N-1) on the tx pin, I've provisionally unplugged all unnecessary cables. From the picture I took, it looks like the projector is sending out this two byte signal expecting the ballast to send back(Arduino code).
All is not lost though as I expect the state change routine I posted before will still be valid as all that is required is a timing reference for sending the three byte sequence.

Is is possible to get the Arduino to monitor say pin 8 for these 9bit bytes, before starting its output?
Title: Re: Projector ballast bypass
Post by: Riva on Aug 10, 2016, 09:04 am
You might be as well just using one of the available modified hardware serial libraries that allow 9 bit serial send and receive and then your responding to the correct commands instead of just hoping the message you receive is what your expecting.
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Aug 13, 2016, 06:56 pm
I had a look at the 9bit serial option when you first mentioned it and from what I've read it looks like more trouble than it's worth.
However since the 9bit tx from the projector is purely needed as a timing reference I have found that it is reliably being interpreted on 2400n1 (8bit) as decimal 81 and 13.
Further to that I accidentally discovered that all the projector needs to start up is the 3 byte sequence, the bytes before that could be some sort of status signal for the lamp as it warms up.

I have also changed the delay from 3.1 seconds on this loop to about 900 milliseconds and it more or less stays on,
it would be much better if I could read the 81 and 13 on the tx line and sync it to the loop, something like this possibly;

if serial read = 13 then

  xSend(x22D, s22D);
  xSend(x139, s139);
  xSend(x2C1, s2C1);

 if serial read = 81 then "go to 10"

I've tried doing it by modifying the "while" loop you posted but did not have any success, apart from my accidental 3 byte "shortcut"
Title: Re: Projector ballast bypass
Post by: Riva on Aug 14, 2016, 09:30 am
Try this one. It just replaces the loop code you used for reading the values using serial and all the xSend routine.
Code: [Select]

while(Serial.available > 0){  // Serial byte(s) available?
  if(Serial.read() == 13){  // Yes, Is it 13
    xSend(x22D, s22D);  // Yes, so send reply
    xSend(x139, s139);
    xSend(x2C1, s2C1);
  }
}


Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Dec 23, 2016, 03:18 am
Lost interest on this but I eventually have the leds I wanted,  have them mounted on heatsinks inside the lightbox
red green and blue.
Will post pictures if all goes to plan.

 
Title: Re: Projector ballast bypass
Post by: Riva on Dec 23, 2016, 08:51 am
Lost interest on this but I eventually have the leds I wanted,  have them mounted on heatsinks inside the lightbox
red green and blue.
Will post pictures if all goes to plan.
That would be good to see the final project. Is the code working as expected now?
Title: Re: Projector ballast bypass
Post by: frankwilsonshat on Dec 30, 2016, 08:04 pm
I'm having to tidy the projector away until after the New Year, so here are two pictures in the meantime.

Been having problems getting the rx opto-isolation part running, however I'm certain your code is going to be 
okay, so will work on that part once I have tidied all the wires up and installed a usb port for 5V.
(Possibly to add Firestick etc...)

The red led is one of those pinkish type colours, it will be getting swapped out for a red led that I have ready to go in.

I've got quite a bright white light coming out of the lens once it's in place, however due to heat constraints I may have to move the leds back from the polarizer filters (plastic frames). If that is the case then there is the possibility for radically expanding the case and fitting 100w leds with condenser lenses.

I have disconnected all non essential fans and run the tacho wires from a working fan to the disconnected tacho lines and the board is happy to run like this, except the main lamp fan which seems to have a different tacho signal, I would like to completely remove this fan, will check it with the SA next year. Could I run some code concurrently with the bit-banging routine, or would I just be as well to use another Arduino?

Happy New Year for now