Open bruno-f-cruz opened 1 year ago
The 2 cameras we are using (for high and low resolution) are both the following model: UI-3360CP-NIR-GL Rev.2. They have a USB 3.0 micro-B that is used for power and we we are also using it to collect the video. It also has a 8-pin Hirose connector (HR25-7TR-8PA(73)), which I guess would be how you connect the cameras to the Harp Behaviour Board. Although I do not know how to do this, I will ask Artur about it.
Camera Model: https://en.ids-imaging.com/download-details/AB00624.html
High Res Framerate: 200.010000 Low Res Framerate: 85.000000
I dont have access to the documentation of these cameras. I can try to get a look at it if you can send me the pdfs to my email.
I am looking into what would be our iDS account so I can have access to the documentation. Until then can you tell me what are you looking for specifically, maybe I can get that information another way.
I would need to know the input line to trigger frames, and the specs of the camera while in "Trigger mode". I am not even sure where that would be. But basically you want to figure out a way to trigger a frame on each rising edge from the camera.
Galvo Mirror Pulse Pal Control Info
Pulse Pal v1.X
BaudRate = 115200; Voltage Range: byte 0:255 = -10V:+10V
Tell me if you need more information
Code controlling pulsepal:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Sardine.Core; using System.Threading; using System.IO.Ports; using FlyVRena2._0.ImageProcessing; using OpenCV.Net;
namespace FlyVRena2._0.External
{
public class PulsePal
public ManualResetEventSlim MREvent = new ManualResetEventSlim(false);
public const int BaudRate = 115200; // Transfer Data rate
const int MaxDataBytes = 35; // Max Size of the Command Data
SerialPort serialPort;
bool initialized;
byte[] readBuffer;
byte[] responseBuffer;
byte[] commandBuffer;
// Pulse Pal Option Bytes For Data Transfer
// 1st byte in command
const byte OpMenu = 0xD5; // All commands should start with the Op menu byte 213
// 2nd byte in command
const byte HandshakeCommand = 0x48; // Option byte 72 ('H') - If Pulse Pal connected, it sends a byte 75 ('K') and firmware byte in response.
const byte SetVoltageCommand = 0x4F; // Option byte 79 - Set a fixed voltage on an output channel
const byte Acknowledge = 0x4B; // Option byte 75 (Program custom pulse train 1)
public PulsePal(string portID)
{
// Serial Port Settings - Pulse Pal v1.X (https://sites.google.com/site/pulsepalwiki/serial-interface)
serialPort = new SerialPort(portID);
serialPort.BaudRate = BaudRate; // Transfer Data rate
serialPort.DataBits = 8; // Transfer Data bit size
serialPort.StopBits = StopBits.One; // Number of stop bits
serialPort.Parity = Parity.None; // Method to detect errors
serialPort.DtrEnable = false; // Data Terminal Ready
serialPort.RtsEnable = true; // Request to Send
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
readBuffer = new byte[serialPort.ReadBufferSize];
commandBuffer = new byte[MaxDataBytes]; // Max Size of the Command Data
responseBuffer = new byte[4];
}
// Initialize Connection To Pulse Pal
public void StartPulsePal()
{
serialPort.Open();
serialPort.ReadExisting();
commandBuffer[0] = OpMenu;
commandBuffer[1] = HandshakeCommand;
serialPort.Write(commandBuffer, 0, 2);
this.Start();
}
protected override void Process(T data)
{
// Updates the voltage input into Pulsepal according to the tracking result
Coordinates coord = new Coordinates() { PixelsCurve = new Point2d(data.position[0], data.position[1]) };
if (data.ID != 0)
{
commandBuffer[0] = OpMenu; // Signal to pulsepal it will receive a command
commandBuffer[1] = SetVoltageCommand; // command pulsepal to set a voltage value
commandBuffer[2] = 1; // 1st Coordenate (X)
commandBuffer[3] = (byte)Math.Round(coord.VoltageCurve.X); // Voltage Value
if (commandBuffer[3] > 255) { commandBuffer[3] = 255; } else if (commandBuffer[3] < 0) { commandBuffer[3] = 0; } // Voltage can't be higher then 255 or lower then 0
serialPort.Write(commandBuffer, 0, 4); // Send Command
commandBuffer[2] = 2; // 2nd Coordenate (Y)
commandBuffer[3] = (byte)Math.Round(coord.VoltageCurve.Y); // Voltage Value
if (commandBuffer[3] > 255) { commandBuffer[3] = 255; } else if (commandBuffer[3] < 0) { commandBuffer[3] = 0; } // Voltage can't be higher then 255 or lower then 0
serialPort.Write(commandBuffer, 0, 4); // Send Command
}
MREvent.Wait();
MREvent.Reset();
}
void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var bytesToRead = serialPort.BytesToRead;
if (serialPort.IsOpen && bytesToRead > 0)
{
bytesToRead = serialPort.Read(readBuffer, 0, bytesToRead);
for (int i = 0; i < bytesToRead; i++)
{
ProcessInput(readBuffer[i]);
}
}
}
void ProcessInput(byte inputData)
{
if (!initialized && inputData != Acknowledge)
{
throw new InvalidOperationException("Unexpected return value from PulsePal.");
}
switch (inputData)
{
case Acknowledge:
initialized = true;
break;
default:
break;
}
}
public void OnExit()
{
this.Stop();
serialPort.Close();
serialPort.Dispose();
MREvent.Dispose();
this.Abort();
}
public void DisposeModule()
{
this.Dispose();
}
}
}
Relative to the camera, I do not know about the trigger. All I have is this photo of the trigger options on the camera user interface. Also, you should have access to the files in the website just by creating an account, you do not need to have it associated with the product.
Mode = Rising edge and send a TTL pulse should produce frames, no?
Right now we do not have the setup set to do that. I am not very knowledgeable on this subject, but I think we will need to order/get some cables to do that, or is the USB connection enough? If so, how can I set/test that? Is there someone I should talk to to help me with this?
Oh I thought you already had the hirose cables. Ye you might be able to connect a jumper wire directly if you just want to test it, but getting the cables is the best option. But yet keep me posted on the user manual and I will be able to provide more help.
On Fri, 24 Feb 2023 at 17:06, miguel-paco @.***> wrote:
Right now we do not have the setup set to do that. I am not very knowledgeable on this subject, but I think we will need to order/get some cables to do that, or is the USB connection enough? If so, how can I set/test that? Is there someone I should talk to to help me with this?
— Reply to this email directly, view it on GitHub https://github.com/neurogears/BonsaiClub/issues/4#issuecomment-1444043230, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABVZBB6WTBC4MBOUDW67FK3WZDTA3ANCNFSM6AAAAAAU4PX4YY . You are receiving this because you authored the thread.Message ID: @.***>
Current hardware streams include:
Suggested solution:
Add an Harp Behavior Board that acquires data from the photodiode (can be digital or analog at 1khz, it doesn't really matter) and simultaneously generates the two PWMs necessary to drive the cameras. Since we have timestamps for all these events given by the same microcontroller, we can easily align post-hoc.
Unfortunately, the behavior board does not natively support a DAC output to drive the galvo mirrors. It is possible to change part of the current-sourcing circuit responsible for driving the "LED" channel and turn it into a DAC. No idea about the temporal benchmarks of this solution, would need to perform some tests. However, since the high-speed camera would not go above 200hz, that would likely be the bottleneck of the closed loop system regardless.
Suggested circuit diagram: